[
  {
    "path": ".gitattributes",
    "content": "* text eol=lf\n\n/.github export-ignore\n/tests export-ignore\n.gitattributes export-ignore\n.gitignore export-ignore\n.travis.yml export-ignore\nphpunit.xml.dist export-ignore\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "# These are supported funding model platforms\n\ngithub: patrickbrouwers\ncustom: https://laravel-excel.com/commercial-support\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/1_Bug_report.yml",
    "content": "name: Bug Report\ndescription: Report a general package issue. Filling in the issue template is mandatory, issues without it will be closed. Please ensure your Laravel-Excel version is still supported (Currently ^3.1)\ntitle: \"[Bug]: \"\nlabels: [bug]\nbody:\n- type: checkboxes\n  id: terms\n  attributes:\n    label: Is the bug applicable and reproducable to the latest version of the package and hasn't it been reported before?\n    description: Currently 3.1.x\n    options:\n    - label: Yes, it's still reproducable\n      required: true     \n- type: input\n  attributes:\n   label: What version of Laravel Excel are you using?\n   description: 'For example: 3.1.30'\n  validations:\n     required: true\n- type: input\n  attributes:\n    label: What version of Laravel are you using?\n    description: 'For example: 7.1.10'\n  validations:\n        required: true\n- type: input\n  attributes:\n    label: What version of PHP are you using?\n    description: 'For example: 8.1.0'\n  validations:\n      required: true  \n- type: textarea\n  attributes:\n    label: Describe your issue\n    description: Describe the problem you're seeing, Please be short, but concise.\n  validations:\n    required: true  \n- type: textarea\n  attributes:\n    label: How can the issue be reproduced?\n    description: Please provide easy-to-reproduce steps (repository, simple code example, failing unit test). Please don't paste your entire code, but create a reproducable scenario that can be tested using a simple User model in a blank Laravel installation.\n  validations:\n    required: true  \n- type: textarea\n  attributes:\n    label: What should be the expected behaviour?\n    description: Please describe what the expected outcome should be. Any suggestions to what is wrong?\n  validations:\n    required: true  \n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "blank_issues_enabled: false\ncontact_links:\n  - name: 🧐 Questions\n    url: https://github.com/SpartnerSoftware/Laravel-Excel/discussions\n    about: The issuer tracker is focused on reporting bugs or problems. Please use the Discussions tabs for questions!\n  - name: 💡 Proposals\n    url: https://github.com/SpartnerSoftware/Laravel-Excel/discussions\n    about: If you have a 🔥 idea. Please use the Discussions tab for this!\n  - name: 📚 Documentation improvements\n    url: https://github.com/SpartnerSoftware/laravel-excel-docs\n    about: Our documentation is open-source, you can make a PR with your suggested changes over there.\n  - name: Commercial Support\n    url: https://laravel-excel.com/commercial-support\n    about: If you need urgent help we can offer this on commercial basis. Send us an e-mail to discuss the posibilities and our hourly rate.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE.md",
    "content": "<!--\nPLEASE READ: FILLING IN THE TEMPLATE IS REQUIRED!\nPLEASE ONLY USE THE ISSUE TRACKER FOR REPORTING BUGS. FOR QUESTIONS USE DISCUSSIONS.\n\nIssues without the issue template will be CLOSED.\n\nHave you read Laravel-Excel's contributing guidelines (https://laravel-excel.maatwebsite.nl/docs/3.1/getting-started/contributing)\nand Code Of Conduct (https://github.com/Maatwebsite/Laravel-Excel/blob/3.1/CODE_OF_CONDUCT.md)?\nBy filing an Issue, you are expected to comply with it, including treating everyone with respect.\n-->\n\n1️⃣ Is the bug applicable and reproducable to the latest version of the package and hasn't it been reported before? (Currently 3.1.x)\n\n2️⃣ What version of the package, Laravel and PHP do you use? Please provide the FULL version number.\n\n- Laravel Excel version: [e.g. 3.1.30]\n- Laravel version: [e.g. 8.3.1]\n- PHP version: [e.g. 7.4.0]\n\n3️⃣ Describe your issue. Please be short, but concise.\n\n4️⃣ How can the issue be reproduced? Please provide easy-to-reproduce steps (repository, simple code example, failing unit test).\n\n5️⃣ What should be the expected behaviour?\n\n6️⃣ Have you filled in the entire issue template? If not, your issue will be closed. Thanks for using the package! 🙌\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "Please take note of our contributing guidelines: https://docs.laravel-excel.com/3.1/getting-started/contributing.html\nFilling out the template is required. Any pull request that does not include enough information to be reviewed in a timely manner may be closed at the maintainers' discretion.\n\n1️⃣  Why should it be added? What are the benefits of this change?\n\n2️⃣  Does it contain multiple, unrelated changes? Please separate the PRs out.\n\n3️⃣  Does it include tests, if possible?\n\n4️⃣  Any drawbacks? Possible breaking changes?\n\n5️⃣  Mark the following tasks as done:\n\n- [ ] Checked the codebase to ensure that your feature doesn't already exist.\n- [ ] Take note of the contributing guidelines.\n- [ ] Checked the pull requests to ensure that another person hasn't already submitted a fix.\n- [ ] Added tests to ensure against regression.\n\n6️⃣  Thanks for contributing! 🙌\n"
  },
  {
    "path": ".github/SUPPORT.md",
    "content": "# Support\n\nThis repository is focused on bugs and issues. We unfortunately can't answer all support questions in a timely manner. Our software is free and open source, meaning that the use of our software is optional.\nWe hold no liability and there is no obligation to support. We will provide support on a best effort basis.\n\nIf you use the software commercially and need elaborate support or need it urgently, we can offer this on a commercial basis. \nPlease contact info@spartner.nl or via phone +31 (0)10 744 9312 or visit the dedicated page with more information:\n\nhttps://laravel-excel.com/commercial-support\n\nAlso note that we are a wrapper package around PhpSpreadsheet and thus we cannot answer all questions that are about PhpSpreadsheet functionality. You could ask your question on Stackoverflow or a Laravel-related forum:\n\n- https://stackoverflow.com/questions/tagged/laravel-excel\n- https://laracasts.com/discuss\n- https://laravel.io/forum\n\nMore information about support you can find in the documentation: https://docs.laravel-excel.com/3.1/getting-started/support.html\n\nThanks!\n"
  },
  {
    "path": ".github/issuecomplete.yml",
    "content": "# The name of the label to apply when an issue does not have all tasks checked\nlabelName: more information needed\n\n# The text of the comment to add to the issue in addition to the label\ncommentText: >\n    Thanks for submitting the ticket. Unfortunately the information you provided is incomplete. We need to know which version you use and how to reproduce it. Please include code examples. Before we can pick it up, please check (https://github.com/Maatwebsite/Laravel-Excel/blob/3.1/.github/ISSUE_TEMPLATE.md) and add the missing information.\n    To make processing of this ticket a lot easier, please make sure to check (https://laravel-excel.maatwebsite.nl/3.1/getting-started/contributing.html) and double-check if you have filled in the issue template correctly. This will allow us to pick up your ticket more efficiently. Issues that don't have an issue template filled in, will be closed.\n\n# Whether or not to ensure all checkboxes are checked\ncheckCheckboxes: false\n\n# Keywords to look for in the body of the issue\nkeywords:\n  - Versions\n  - Description\n"
  },
  {
    "path": ".github/stale.yml",
    "content": "# Number of days of inactivity before an issue becomes stale\ndaysUntilStale: 60\n# Number of days of inactivity before a stale issue is closed\ndaysUntilClose: 1\n# Issues with these labels will never be considered stale\nexemptLabels:\n  - pinned\n  - proposal\n# Label to use when marking an issue as stale\nstaleLabel: stale\n# Comment to post when marking an issue as stale. Set to `false` to disable\nmarkComment: false\n# Comment to post when closing a stale issue. Set to `false` to disable\ncloseComment: >\n  This bug report has been automatically closed because it has not had\n  recent activity. If this is still an active bug, please comment to reopen. \n  Thank you for your contributions. \n"
  },
  {
    "path": ".github/workflows/run-tests.yml",
    "content": "name: Run tests\n\non:\n  push:\n  pull_request:\n  schedule:\n    - cron: '0 0 * * *'\n\njobs:\n  tests:\n    if: \"!contains(github.event.head_commit.message, 'skip ci')\"\n    runs-on: ${{ matrix.os }}\n\n    services:\n      mysql:\n        image: mysql:5.7\n        env:\n          MYSQL_DATABASE: laravel_excel\n          MYSQL_ALLOW_EMPTY_PASSWORD: yes\n        ports:\n          - 3306\n        options: --health-cmd=\"mysqladmin ping\" --health-interval=10s --health-timeout=5s --health-retries=3\n\n    strategy:\n      matrix:\n        php: [7.4, 8.0, 8.1, 8.2, 8.3, 8.4, 8.5]\n        laravel: [13, 12, 11, 10, 9, 8, 7, 6, 5.8]\n        dependency-version: [prefer-stable]\n        os: [ubuntu-latest]\n        include:\n          - laravel: 13\n            scout: 11.*\n            testbench: 11.*\n          - laravel: 12\n            scout: 10.*\n            testbench: 10.*\n          - laravel: 11\n            scout: 10.*\n            testbench: 9.*\n          - laravel: 10\n            scout: 10.*\n            testbench: 8.*\n          - laravel: 9\n            scout: 9.*\n            testbench: 7.*\n          - laravel: 8\n            scout: 8.*\n            testbench: 6.*\n          - laravel: 7\n            scout: 7.2.*\n            testbench: 5.*\n          - laravel: 6\n            scout: 7.1.*\n            testbench: 4.*\n          - laravel: 5.8\n            scout: 7.1.*\n            testbench: 3.8.*\n        exclude:\n          - laravel: 13\n            php: 8.2\n          - laravel: 13\n            php: 8.1\n          - laravel: 13\n            php: 8.0\n          - laravel: 13\n            php: 7.4\n          - laravel: 12\n            php: 8.1\n          - laravel: 12\n            php: 8.0\n          - laravel: 12\n            php: 7.4\n          - laravel: 11\n            php: 8.5\n          - laravel: 11\n            php: 8.1\n          - laravel: 11\n            php: 8.0\n          - laravel: 11\n            php: 7.4\n          - laravel: 10\n            php: 8.0\n          - laravel: 10\n            php: 7.4\n          - laravel: 10\n            php: 8.4\n          - laravel: 10\n            php: 8.5\n          - laravel: 9\n            php: 7.4\n          - laravel: 9\n            php: 8.4\n          - laravel: 9\n            php: 8.5\n          - laravel: 8\n            php: 8.4\n          - laravel: 8\n            php: 8.5\n          - laravel: 7\n            php: 8.0\n          - laravel: 7\n            php: 8.1\n          - laravel: 7\n            php: 8.2\n          - laravel: 7\n            php: 8.3\n          - laravel: 7\n            php: 8.4\n          - laravel: 7\n            php: 8.5\n          - laravel: 6\n            php: 8.0\n          - laravel: 6\n            php: 8.1\n          - laravel: 6\n            php: 8.2\n          - laravel: 6\n            php: 8.3\n          - laravel: 6\n            php: 8.4\n          - laravel: 6\n            php: 8.5\n          - laravel: 5.8\n            php: 8.0\n          - laravel: 5.8\n            php: 8.1\n          - laravel: 5.8\n            php: 8.2\n          - laravel: 5.8\n            php: 8.3\n          - laravel: 5.8\n            php: 8.4\n          - laravel: 5.8\n            php: 8.5\n\n    name: PHP${{ matrix.php }} - L${{ matrix.laravel }}\n\n    steps:\n      - name: Checkout code\n        uses: actions/checkout@v4\n\n      - name: Cache dependencies\n        uses: actions/cache@v4\n        with:\n          path: ~/.composer/cache/files\n          key: dependency-cache-laravel-${{ matrix.laravel }}-php-${{ matrix.php }}-composer-${{ hashFiles('composer.json') }}\n\n      - name: Setup PHP\n        uses: shivammathur/setup-php@v2\n        with:\n          php-version: ${{ matrix.php }}\n          extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, mysql, pdo_mysql, bcmath, intl, gd, exif, iconv\n          coverage: none\n\n      - name: Install dependencies\n        run: |\n          composer require \"laravel/framework:${{ matrix.laravel }}.*\" \"orchestra/testbench:${{ matrix.testbench }}\" \"laravel/scout:${{ matrix.scout }}\"  --no-interaction --no-update\n          composer update --${{ matrix.dependency-version }} --no-interaction\n\n      - name: Install legacy factories\n        run: |\n          composer require \"laravel/legacy-factories\" -W --no-interaction\n        if: \"matrix.laravel >= 8\"\n\n      - name: Execute tests\n        run: vendor/bin/phpunit --testdox --configuration phpunit.xml.dist\n        env:\n          DB_PORT: ${{ job.services.mysql.ports[3306] }}\n"
  },
  {
    "path": ".gitignore",
    "content": "/vendor\ncomposer.phar\ncomposer.lock\n.DS_Store\n.idea\nphpunit.xml\n.phpunit.result.cache"
  },
  {
    "path": ".phpunit.cache/test-results",
    "content": "{\"version\":1,\"defects\":{\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedImportTest::can_queue_an_import_with_batch_cache\":5,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedExportTest::can_queue_an_export_with_batch_cache\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedQueryExportTest::can_queue_an_export_with_batch_cache\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromQueryTest::can_export_from_query\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromQueryTest::can_export_from_relation_query_queued\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromQueryTest::can_export_from_query_with_eager_loads\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromQueryTest::can_export_from_query_with_eager_loads_and_queued\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromQueryTest::can_export_from_query_builder_without_using_eloquent\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromQueryTest::can_export_from_query_builder_without_using_eloquent_and_queued\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromQueryTest::can_export_from_query_builder_with_nested_arrays\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromQueryTest::can_export_from_query_builder_with_nested_arrays_queued\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromQueryTest::can_export_from_query_with_batch_caching\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromQueryTest::can_export_from_query_with_prepare_rows\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromQueryTest::can_export_from_scout\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromViewTest::can_export_from_view\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromViewTest::can_export_multiple_sheets_from_view\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ImportableTest::can_import_a_simple_xlsx_file\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ImportableTest::can_import_a_simple_xlsx_file_from_uploaded_file\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ImportableTest::can_import_a_simple_csv_file_with_html_tags_inside\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ImportableTest::can_import_a_simple_xlsx_file_with_ignore_empty_set_to_true\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ImportableTest::can_import_a_simple_xlsx_file_with_ignore_empty_set_to_false\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\OnEachRowTest::can_import_each_row_individually\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\OnEachRowTest::it_respects_the_end_column\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\RegistersEventListenersTest::events_get_called_when_importing\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\RemembersChunkOffsetTest::can_access_chunk_offset_on_import_to_array_in_chunks\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\RemembersRowNumberTest::can_access_row_number_on_import_to_model\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\RemembersRowNumberTest::can_access_row_number_on_import_to_array_in_chunks\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\RemembersRowNumberTest::can_access_row_number_on_import_to_array_in_chunks_with_batch_inserts\":8,\"ShouldQueueWithoutChainTest::can_import_to_model_in_chunks\":8,\"ShouldQueueWithoutChainTest::can_import_to_model_without_job_chaining\":8,\"ShouldQueueWithoutChainTest::a_queue_name_can_be_specified_when_importing\":8,\"ShouldQueueWithoutChainTest::the_cleanup_only_runs_when_all_jobs_are_done\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\SkipsEmptyRowsTest::skips_empty_rows_when_importing_to_collection\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\SkipsEmptyRowsTest::skips_empty_rows_when_importing_on_each_row\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\SkipsEmptyRowsTest::skips_empty_rows_when_importing_to_model\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\SkipsEmptyRowsTest::custom_skips_rows_when_importing_to_collection\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\SkipsEmptyRowsTest::custom_skips_rows_when_importing_to_model\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\SkipsEmptyRowsTest::custom_skips_rows_when_using_oneachrow\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\SkipsOnErrorTest::can_skip_on_error\":7,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\SkipsOnErrorTest::can_skip_errors_and_collect_all_errors_at_the_end\":7,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\SkipsOnFailureTest::can_skip_on_error\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\SkipsOnFailureTest::skips_only_failed_rows_in_batch\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\SkipsOnFailureTest::can_skip_failures_and_collect_all_failures_at_the_end\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\SkipsOnFailureTest::can_validate_using_oneachrow_and_skipsonfailure\":7,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\SkipsOnFailureTest::can_validate_using_tocollection_and_skipsonfailure\":7,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ToArrayTest::can_import_to_array\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ToArrayTest::can_import_multiple_sheets_to_array\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ToCollectionTest::can_import_to_collection\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ToCollectionTest::can_import_multiple_sheets_to_collection\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ToModelTest::can_import_each_row_to_model\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ToModelTest::has_timestamps_when_imported_single_model\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ToModelTest::can_import_multiple_models_in_single_to_model\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ToModelTest::can_import_multiple_different_types_of_models_in_single_to_model\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithBatchInsertsTest::can_import_to_model_in_batches\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithBatchInsertsTest::can_import_to_model_in_batches_bigger_file\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithBatchInsertsTest::can_import_multiple_different_types_of_models_in_single_to_model\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithBatchInsertsTest::has_timestamps_when_imported_in_batches\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCalculatedFormulasTest::by_default_does_not_calculate_formulas\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCalculatedFormulasTest::can_import_to_array_with_calculated_formulas\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCalculatedFormulasTest::can_import_to_model_with_calculated_formulas\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCalculatedFormulasTest::can_import_to_array_with_calculated_formulas_and_multi_sheet_references\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCalculatedFormulasTest::can_import_to_array_with_calculated_formulas_and_skips_empty\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCalculatedFormulasTest::can_import_to_model_with_calculated_formulas_and_skips_empty\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithChunkReadingTest::can_import_to_model_in_chunks_un\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithChunkReadingTest::can_import_to_model_in_chunks_and_insert_in_batches\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithChunkReadingTest::can_import_to_model_in_chunks_and_insert_in_batches_with_heading_row\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithChunkReadingTest::can_import_csv_in_chunks_and_insert_in_batches\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithChunkReadingTest::can_import_to_model_in_chunks_and_insert_in_batches_with_multiple_sheets\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithChunkReadingTest::can_import_to_array_in_chunks\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithChunkReadingTest::can_import_to_model_in_chunks_and_insert_in_batches_with_multiple_sheets_objects_by_index\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithChunkReadingTest::can_import_to_model_in_chunks_and_insert_in_batches_with_multiple_sheets_objects_by_name\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithChunkReadingTest::can_catch_job_failed_in_chunks\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithChunkReadingTest::can_import_to_array_and_format_in_chunks\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithChunkReadingTest::can_import_to_array_in_chunks_without_formatting\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithColumnLimitTest::can_import_to_array_with_column_limit\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithColumnLimitTest::can_import_to_array_with_column_limit_and_skips_empty_rows\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithConditionalSheetsTest::can_select_which_sheets_will_be_imported\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCustomCsvSettingsTest::can_read_csv_import_with_custom_settings\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCustomCsvSettingsTest::cannot_read_with_wrong_delimiter\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCustomQuerySizeTest::can_export_with_custom_count\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCustomValueBinderTest::can_set_a_value_binder_on_import\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithEventsTest::import_events_get_called\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithEventsTest::import_chunked_events_get_called\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithFormatDataTest::by_default_import_to_array\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithFormatDataTest::can_import_to_array_with_format_data\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithFormatDataTest::can_import_to_array_with_format_data_and_skips_empty_rows\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithFormatDataTest::by_default_import_to_collection\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithFormatDataTest::can_import_to_collection_with_format_data\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithFormatDataTest::by_default_import_to_model\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithFormatDataTest::can_import_to_model_with_format_data\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithGroupedHeadingRowTest::can_import_to_array_with_grouped_headers\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithGroupedHeadingRowTest::can_import_oneachrow_with_grouped_headers\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithGroupedHeadingRowTest::can_import_to_collection_with_grouped_headers\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithGroupedHeadingRowTest::can_import_each_row_to_model_with_grouped_headers\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithHeadingRowTest::can_import_each_row_to_model_with_heading_row\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithHeadingRowTest::can_import_each_row_to_model_with_different_heading_row\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithHeadingRowTest::can_import_to_array_with_heading_row\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithHeadingRowTest::can_import_empty_rows_with_header\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithHeadingRowTest::can_import_empty_models_with_header\":7,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithHeadingRowTest::can_cast_empty_headers_to_indexed_int\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithLimitTest::can_import_a_limited_section_of_rows_to_model_with_different_start_row\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithLimitTest::can_import_to_array_with_limit\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithLimitTest::can_set_limit_bigger_than_row_size\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMappedCellsTest::can_import_with_references_to_cells\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMappedCellsTest::can_import_with_nested_references_to_cells\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMappedCellsTest::can_import_with_references_to_cells_to_model\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMultipleSheetsTest::can_export_with_multiple_sheets_using_collections\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMultipleSheetsTest::can_export_multiple_sheets_from_view\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMultipleSheetsTest::unknown_sheet_index_will_throw_sheet_not_found_exception\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMultipleSheetsTest::unknown_sheet_name_will_throw_sheet_not_found_exception\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMultipleSheetsTest::unknown_sheet_name_can_be_ignored\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMultipleSheetsTest::unknown_sheet_indices_can_be_ignored_per_name\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMultipleSheetsTest::unknown_sheet_indices_can_be_ignored\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMultipleSheetsTest::unknown_sheet_indices_can_be_ignored_per_sheet\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMultipleSheetsTest::can_import_multiple_sheets\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMultipleSheetsTest::can_import_multiple_sheets_by_sheet_name\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMultipleSheetsTest::can_import_multiple_sheets_by_sheet_index_and_name\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMultipleSheetsTest::can_import_multiple_sheets_by_sheet_name_and_index\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithStartRowTest::can_import_each_row_to_model_with_different_start_row\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithStartRowTest::can_import_to_array_with_start_row\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithUpsertsTest::can_upsert_models_in_batches\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithUpsertsTest::can_upsert_models_in_rows\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithUpsertsTest::can_upsert_models_in_batches_with_defined_upsert_columns\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithUpsertsTest::can_upsert_models_in_rows_with_defined_upsert_columns\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::can_validate_rows\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::can_validate_rows_with_closure_validation_rules\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::can_validate_rows_with_custom_validation_rule_objects\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::can_validate_rows_with_conditionality\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::can_validate_rows_with_unless_conditionality\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::can_validate_rows_with_combined_rules_with_colons\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::can_validate_with_custom_attributes\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::can_validate_with_custom_message\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::can_validate_rows_with_headings\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::can_validate_rows_with_grouped_headings\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::can_validate_rows_in_batches\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::can_validate_using_oneachrow\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::can_validate_using_collection\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::can_validate_using_array\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::can_configure_validator\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::can_prepare_using_toarray\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::can_prepare_using_tocollection\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::can_prepare_using_tomodel\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::can_prepare_using_oneachrow\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::can_prepare_using_skipsemptyrows\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::can_import_a_simple_xlsx_file\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::can_import_a_tsv_file\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::can_chain_imports\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::can_import_a_simple_xlsx_file_from_uploaded_file\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::can_import_a_simple_xlsx_file_from_real_path\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::can_import_without_extension_with_explicit_reader_type\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\StoreCollectionTest::can_store_a_model_collection_with_headings_as_excel\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedImportTest::cannot_queue_import_that_does_not_implement_should_queue\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedImportTest::can_queue_an_import\":7,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedImportTest::can_queue_an_import_with_batch_cache_and_file_store\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedImportTest::can_queue_import_with_remote_temp_disk\":7,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedImportTest::can_keep_extension_for_temp_file_on_remote_disk\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedImportTest::can_queue_import_with_remote_temp_disk_and_prefix\":7,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedImportTest::can_automatically_delete_temp_file_on_failure_when_using_remote_disk\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedImportTest::cannot_automatically_delete_temp_file_on_failure_when_using_local_disk\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedImportTest::can_force_remote_download_and_deletion_for_each_chunk_on_queue\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedImportTest::can_define_middleware_method_on_queued_import\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedImportTest::can_define_retry_until_method_on_queued_import\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedImportTest::can_define_max_exceptions_property_on_queued_import\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedQueryExportTest::can_queue_an_export\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedQueryExportTest::can_queue_an_export_with_batch_cache_and_file_store\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedQueryExportTest::can_queue_an_export_with_mapping\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedQueryExportTest::can_queue_scout_export\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedViewExportTest::can_queue_an_export\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedViewExportTest::can_export_multiple_sheets_from_view\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromCollectionTest::can_export_from_lazy_collection\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\CellTest::can_get_cell_value\":7,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithEventsTest::export_chunked_events_get_called\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromArrayTest::can_export_from_array\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromCollectionTest::can_export_from_collection\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromCollectionTest::can_export_with_multiple_sheets_from_collection\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromCollectionTest::can_export_from_lazy_collection_with_queue\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithColumnFormattingTest::can_export_with_column_formatting\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithColumnWidthsTest::can_set_column_width\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCustomCsvSettingsTest::can_store_csv_export_with_custom_settings\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCustomCsvSettingsTest::can_store_csv_export_with_custom_encoding\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCustomStartCellTest::can_store_collection_with_custom_start_cell\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCustomValueBinderTest::can_set_a_value_binder_on_export\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithDefaultStylesTest::can_configure_default_styles\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithHeadingsTest::can_export_from_collection_with_heading_row\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithHeadingsTest::can_export_from_collection_with_multiple_heading_rows\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithHeadingsTest::can_export_from_collection_with_heading_row_with_custom_start_cell\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMappingTest::can_export_with_heading\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMappingTest::can_return_multiple_rows_in_map\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMappingTest::json_array_columns_shouldnt_be_detected_as_multiple_rows\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithStrictNullComparisonTest::exported_zero_values_are_not_null_when_exporting_with_strict_null_comparison\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithStrictNullComparisonTest::exported_zero_values_are_null_when_not_exporting_with_strict_null_comparison\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithStrictNullComparisonTest::exports_trailing_empty_cells\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithStrictNullComparisonTest::exports_trailing_empty_cells_by_setting_config_strict_null_comparison\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithStylesTest::can_configure_styles\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::can_store_csv_export_with_custom_settings\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\DownloadCollectionTest::can_download_a_collection_as_excel\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\DownloadCollectionTest::can_download_a_collection_with_headers_as_excel\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\DownloadCollectionTest::can_download_collection_with_headers_with_hidden_eloquent_attributes\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\DownloadCollectionTest::can_download_collection_with_headers_when_making_attributes_visible\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\DownloadCollectionTest::can_set_custom_response_headers\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\DownloadQueryMacroTest::can_download_a_query_as_excel\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\DownloadQueryMacroTest::can_download_a_collection_with_headers_as_excel\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\ImportAsMacroTest::can_import_directly_into_a_model_with_mapping\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\ImportMacroTest::can_import_directly_into_a_model\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\StoreCollectionTest::can_store_a_collection_as_excel\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\StoreCollectionTest::can_store_a_collection_as_excel_on_non_default_disk\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\StoreCollectionTest::can_store_a_collection_with_headings_as_excel\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\StoreQueryMacroTest::can_download_a_query_as_excel\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\StoreQueryMacroTest::can_download_a_query_as_excel_on_different_disk\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\StoreQueryMacroTest::can_store_a_query_with_headers_as_excel\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedExportTest::can_queue_an_export\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedExportTest::can_queue_an_export_and_store_on_different_disk\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedExportTest::can_queue_export_with_remote_temp_disk\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedExportTest::can_queue_export_with_remote_temp_disk_and_prefix\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedExportTest::can_implicitly_queue_an_export\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedExportTest::can_queue_export_with_mapping_on_eloquent_models\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedExportTest::can_set_locale_on_queue_export_job\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedExportTest::can_queue_export_not_flushing_the_cache\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ToModelTest::can_import_models_with_belongs_to_relations\":7,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ToModelTest::can_import_models_with_belongs_to_many_relations\":7,\"Maatwebsite\\\\Excel\\\\Tests\\\\Cache\\\\BatchCacheTest::it_writes_to_cache_with_a_dateinterval_ttl\":7,\"Maatwebsite\\\\Excel\\\\Tests\\\\HeadingRowImportTest::can_import_only_heading_row\":5,\"Maatwebsite\\\\Excel\\\\Tests\\\\HeadingRowImportTest::can_import_only_heading_row_with_custom_heading_row_formatter\":5,\"Maatwebsite\\\\Excel\\\\Tests\\\\HeadingRowImportTest::can_import_only_heading_row_with_custom_heading_row_formatter_with_key\":5,\"Maatwebsite\\\\Excel\\\\Tests\\\\HeadingRowImportTest::can_import_only_heading_row_with_custom_row_number\":5,\"Maatwebsite\\\\Excel\\\\Tests\\\\HeadingRowImportTest::can_import_only_heading_row_for_multiple_sheets\":5,\"Maatwebsite\\\\Excel\\\\Tests\\\\HeadingRowImportTest::can_import_only_heading_row_for_multiple_sheets_with_key\":5,\"Maatwebsite\\\\Excel\\\\Tests\\\\HeadingRowImportTest::can_import_only_heading_row_for_multiple_sheets_with_custom_row_number\":5,\"Maatwebsite\\\\Excel\\\\Tests\\\\HeadingRowImportTest::can_import_heading_row_with_custom_formatter_defined_in_config\":5,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ImportableTest::test_cannot_import_a_non_existing_xlsx_file\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromQueryTest::test_can_export_from_query\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromQueryTest::test_can_export_from_relation_query_queued\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromQueryTest::test_can_export_from_query_with_eager_loads\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromQueryTest::test_can_export_from_query_with_eager_loads_and_queued\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromQueryTest::test_can_export_from_query_builder_without_using_eloquent\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromQueryTest::test_can_export_from_query_builder_without_using_eloquent_and_queued\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromQueryTest::test_can_export_from_query_builder_with_nested_arrays\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromQueryTest::test_can_export_from_query_builder_with_nested_arrays_queued\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromQueryTest::test_can_export_from_query_with_batch_caching\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromQueryTest::test_can_export_from_query_with_prepare_rows\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromQueryTest::test_can_export_from_scout\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromViewTest::test_can_export_from_view\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromViewTest::test_can_export_multiple_sheets_from_view\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ImportableTest::test_can_import_a_simple_xlsx_file\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ImportableTest::test_can_import_a_simple_xlsx_file_from_uploaded_file\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ImportableTest::test_can_import_a_simple_csv_file_with_html_tags_inside\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ImportableTest::test_can_import_a_simple_xlsx_file_with_ignore_empty_set_to_true\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ImportableTest::test_can_import_a_simple_xlsx_file_with_ignore_empty_set_to_false\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\OnEachRowTest::test_can_import_each_row_individually\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\OnEachRowTest::test_it_respects_the_end_column\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\RegistersEventListenersTest::test_events_get_called_when_importing\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\RemembersChunkOffsetTest::test_can_access_chunk_offset_on_import_to_array_in_chunks\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\RemembersRowNumberTest::test_can_access_row_number_on_import_to_model\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\RemembersRowNumberTest::test_can_access_row_number_on_import_to_array_in_chunks\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\RemembersRowNumberTest::test_can_access_row_number_on_import_to_array_in_chunks_with_batch_inserts\":8,\"ShouldQueueWithoutChainTest::test_can_import_to_model_in_chunks\":8,\"ShouldQueueWithoutChainTest::test_can_import_to_model_without_job_chaining\":8,\"ShouldQueueWithoutChainTest::test_a_queue_name_can_be_specified_when_importing\":8,\"ShouldQueueWithoutChainTest::test_the_cleanup_only_runs_when_all_jobs_are_done\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\SkipsEmptyRowsTest::test_skips_empty_rows_when_importing_to_collection\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\SkipsEmptyRowsTest::test_skips_empty_rows_when_importing_on_each_row\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\SkipsEmptyRowsTest::test_skips_empty_rows_when_importing_to_model\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\SkipsEmptyRowsTest::test_custom_skips_rows_when_importing_to_collection\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\SkipsEmptyRowsTest::test_custom_skips_rows_when_importing_to_model\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\SkipsEmptyRowsTest::test_custom_skips_rows_when_using_oneachrow\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\SkipsOnErrorTest::test_can_skip_on_error\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\SkipsOnErrorTest::test_can_skip_errors_and_collect_all_errors_at_the_end\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\SkipsOnFailureTest::test_can_skip_on_error\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\SkipsOnFailureTest::test_skips_only_failed_rows_in_batch\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\SkipsOnFailureTest::test_can_skip_failures_and_collect_all_failures_at_the_end\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\SkipsOnFailureTest::test_can_validate_using_oneachrow_and_skipsonfailure\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\SkipsOnFailureTest::test_can_validate_using_tocollection_and_skipsonfailure\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ToArrayTest::test_can_import_to_array\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ToArrayTest::test_can_import_multiple_sheets_to_array\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ToCollectionTest::test_can_import_to_collection\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ToCollectionTest::test_can_import_multiple_sheets_to_collection\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ToModelTest::test_can_import_each_row_to_model\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ToModelTest::test_has_timestamps_when_imported_single_model\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ToModelTest::test_can_import_multiple_models_in_single_to_model\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ToModelTest::test_can_import_multiple_different_types_of_models_in_single_to_model\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ToModelTest::test_can_import_models_with_belongs_to_relations\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ToModelTest::test_can_import_models_with_belongs_to_many_relations\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithBatchInsertsTest::test_can_import_to_model_in_batches\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithBatchInsertsTest::test_can_import_to_model_in_batches_bigger_file\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithBatchInsertsTest::test_can_import_multiple_different_types_of_models_in_single_to_model\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithBatchInsertsTest::test_has_timestamps_when_imported_in_batches\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCalculatedFormulasTest::test_by_default_does_not_calculate_formulas\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCalculatedFormulasTest::test_can_import_to_array_with_calculated_formulas\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCalculatedFormulasTest::test_can_import_to_model_with_calculated_formulas\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCalculatedFormulasTest::test_can_import_to_array_with_calculated_formulas_and_multi_sheet_references\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCalculatedFormulasTest::test_can_import_to_array_with_calculated_formulas_and_skips_empty\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCalculatedFormulasTest::test_can_import_to_model_with_calculated_formulas_and_skips_empty\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithChunkReadingTest::test_can_import_to_model_in_chunks_un\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithChunkReadingTest::test_can_import_to_model_in_chunks_and_insert_in_batches\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithChunkReadingTest::test_can_import_to_model_in_chunks_and_insert_in_batches_with_heading_row\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithChunkReadingTest::test_can_import_csv_in_chunks_and_insert_in_batches\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithChunkReadingTest::test_can_import_to_model_in_chunks_and_insert_in_batches_with_multiple_sheets\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithChunkReadingTest::test_can_import_to_array_in_chunks\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithChunkReadingTest::test_can_import_to_model_in_chunks_and_insert_in_batches_with_multiple_sheets_objects_by_index\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithChunkReadingTest::test_can_import_to_model_in_chunks_and_insert_in_batches_with_multiple_sheets_objects_by_name\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithChunkReadingTest::test_can_catch_job_failed_in_chunks\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithChunkReadingTest::test_can_import_to_array_and_format_in_chunks\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithChunkReadingTest::test_can_import_to_array_in_chunks_without_formatting\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithColumnLimitTest::test_can_import_to_array_with_column_limit\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithColumnLimitTest::test_can_import_to_array_with_column_limit_and_skips_empty_rows\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithConditionalSheetsTest::test_can_select_which_sheets_will_be_imported\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCustomCsvSettingsTest::test_can_read_csv_import_with_custom_settings\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCustomCsvSettingsTest::test_cannot_read_with_wrong_delimiter\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCustomQuerySizeTest::test_can_export_with_custom_count\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCustomValueBinderTest::test_can_set_a_value_binder_on_import\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithEventsTest::test_import_events_get_called\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithEventsTest::test_import_chunked_events_get_called\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithEventsTest::test_export_chunked_events_get_called\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithFormatDataTest::test_by_default_import_to_array\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithFormatDataTest::test_can_import_to_array_with_format_data\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithFormatDataTest::test_can_import_to_array_with_format_data_and_skips_empty_rows\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithFormatDataTest::test_by_default_import_to_collection\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithFormatDataTest::test_can_import_to_collection_with_format_data\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithFormatDataTest::test_by_default_import_to_model\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithFormatDataTest::test_can_import_to_model_with_format_data\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithGroupedHeadingRowTest::test_can_import_to_array_with_grouped_headers\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithGroupedHeadingRowTest::test_can_import_oneachrow_with_grouped_headers\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithGroupedHeadingRowTest::test_can_import_to_collection_with_grouped_headers\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithGroupedHeadingRowTest::test_can_import_each_row_to_model_with_grouped_headers\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithHeadingRowTest::test_can_import_each_row_to_model_with_heading_row\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithHeadingRowTest::test_can_import_each_row_to_model_with_different_heading_row\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithHeadingRowTest::test_can_import_to_array_with_heading_row\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithHeadingRowTest::test_can_import_empty_rows_with_header\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithHeadingRowTest::test_can_import_empty_models_with_header\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithHeadingRowTest::test_can_cast_empty_headers_to_indexed_int\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithLimitTest::test_can_import_a_limited_section_of_rows_to_model_with_different_start_row\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithLimitTest::test_can_import_to_array_with_limit\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithLimitTest::test_can_set_limit_bigger_than_row_size\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMappedCellsTest::test_can_import_with_references_to_cells\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMappedCellsTest::test_can_import_with_nested_references_to_cells\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMappedCellsTest::test_can_import_with_references_to_cells_to_model\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMultipleSheetsTest::test_can_export_with_multiple_sheets_using_collections\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMultipleSheetsTest::test_can_export_multiple_sheets_from_view\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMultipleSheetsTest::test_unknown_sheet_index_will_throw_sheet_not_found_exception\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMultipleSheetsTest::test_unknown_sheet_name_will_throw_sheet_not_found_exception\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMultipleSheetsTest::test_unknown_sheet_name_can_be_ignored\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMultipleSheetsTest::test_unknown_sheet_indices_can_be_ignored_per_name\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMultipleSheetsTest::test_unknown_sheet_indices_can_be_ignored\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMultipleSheetsTest::test_unknown_sheet_indices_can_be_ignored_per_sheet\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMultipleSheetsTest::test_can_import_multiple_sheets\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMultipleSheetsTest::test_can_import_multiple_sheets_by_sheet_name\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMultipleSheetsTest::test_can_import_multiple_sheets_by_sheet_index_and_name\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMultipleSheetsTest::test_can_import_multiple_sheets_by_sheet_name_and_index\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithStartRowTest::test_can_import_each_row_to_model_with_different_start_row\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithStartRowTest::test_can_import_to_array_with_start_row\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithUpsertsTest::test_can_upsert_models_in_batches\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithUpsertsTest::test_can_upsert_models_in_rows\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithUpsertsTest::test_can_upsert_models_in_batches_with_defined_upsert_columns\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithUpsertsTest::test_can_upsert_models_in_rows_with_defined_upsert_columns\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::test_can_validate_rows\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::test_can_validate_rows_with_closure_validation_rules\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::test_can_validate_rows_with_custom_validation_rule_objects\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::test_can_validate_rows_with_conditionality\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::test_can_validate_rows_with_unless_conditionality\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::test_can_validate_rows_with_combined_rules_with_colons\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::test_can_validate_with_custom_attributes\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::test_can_validate_with_custom_attributes_pointing_to_another_attribute\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::test_can_validate_with_custom_message\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::test_can_validate_rows_with_headings\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::test_can_validate_rows_with_grouped_headings\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::test_can_validate_rows_in_batches\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::test_can_validate_using_oneachrow\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::test_can_validate_using_collection\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::test_can_validate_using_array\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::test_can_configure_validator\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::test_can_prepare_using_toarray\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::test_can_prepare_using_tocollection\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::test_can_prepare_using_tomodel\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::test_can_prepare_using_oneachrow\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::test_can_prepare_using_skipsemptyrows\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::test_can_import_a_simple_xlsx_file\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::test_can_import_a_tsv_file\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::test_can_chain_imports\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::test_can_import_a_simple_xlsx_file_from_uploaded_file\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::test_can_import_a_simple_xlsx_file_from_real_path\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::test_can_import_without_extension_with_explicit_reader_type\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\DownloadQueryMacroTest::test_can_download_a_query_as_excel\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\DownloadQueryMacroTest::test_can_download_a_collection_with_headers_as_excel\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\ImportAsMacroTest::test_can_import_directly_into_a_model_with_mapping\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\ImportMacroTest::test_can_import_directly_into_a_model\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\StoreCollectionTest::test_can_store_a_model_collection_with_headings_as_excel\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\StoreQueryMacroTest::test_can_download_a_query_as_excel\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\StoreQueryMacroTest::test_can_download_a_query_as_excel_on_different_disk\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\StoreQueryMacroTest::test_can_store_a_query_with_headers_as_excel\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedImportTest::test_cannot_queue_import_that_does_not_implement_should_queue\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedImportTest::test_can_queue_an_import\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedImportTest::test_can_queue_an_import_with_batch_cache_and_file_store\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedImportTest::test_can_queue_import_with_remote_temp_disk\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedImportTest::test_can_keep_extension_for_temp_file_on_remote_disk\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedImportTest::test_can_queue_import_with_remote_temp_disk_and_prefix\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedImportTest::test_can_automatically_delete_temp_file_on_failure_when_using_remote_disk\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedImportTest::test_cannot_automatically_delete_temp_file_on_failure_when_using_local_disk\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedImportTest::test_can_force_remote_download_and_deletion_for_each_chunk_on_queue\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedImportTest::test_can_define_middleware_method_on_queued_import\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedImportTest::test_can_define_retry_until_method_on_queued_import\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedImportTest::test_can_define_max_exceptions_property_on_queued_import\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedQueryExportTest::test_can_queue_an_export\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedQueryExportTest::test_can_queue_an_export_with_batch_cache_and_file_store\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedQueryExportTest::test_can_queue_an_export_with_mapping\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedQueryExportTest::test_can_queue_scout_export\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedViewExportTest::test_can_queue_an_export\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedViewExportTest::test_can_export_multiple_sheets_from_view\":8,\"Maatwebsite\\\\Excel\\\\Tests\\\\Validators\\\\RowValidatorTest::test_format_rule_with_string_input_matching_pattern\":7,\"Maatwebsite\\\\Excel\\\\Tests\\\\Validators\\\\RowValidatorTest::test_format_rule_with_required_without_all\":7,\"Maatwebsite\\\\Excel\\\\Tests\\\\Validators\\\\RowValidatorTest::test_format_rule_with_required_without\":7},\"times\":{\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedImportTest::can_queue_an_import_with_batch_cache\":2.346,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedExportTest::can_queue_an_export\":0.241,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedExportTest::can_queue_an_export_with_batch_cache\":0.067,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedQueryExportTest::can_queue_an_export_with_batch_cache\":0.374,\"Maatwebsite\\\\Excel\\\\Tests\\\\Cache\\\\BatchCacheTest::will_get_multiple_from_memory_if_cells_hold_in_memory\":0.02,\"Maatwebsite\\\\Excel\\\\Tests\\\\Cache\\\\BatchCacheTest::will_get_multiple_from_cache_if_cells_are_persisted\":0.002,\"Maatwebsite\\\\Excel\\\\Tests\\\\Cache\\\\BatchCacheTest::will_get_multiple_from_cache_and_persisted\":0.001,\"Maatwebsite\\\\Excel\\\\Tests\\\\Cache\\\\BatchCacheTest::it_persists_to_cache_when_memory_limit_reached_on_setting_a_value\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\Cache\\\\BatchCacheTest::it_persists_to_cache_when_memory_limit_reached_on_setting_multiple_values\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\Cache\\\\BatchCacheTest::it_writes_to_cache_with_default_ttl#null (forever)\":0.001,\"Maatwebsite\\\\Excel\\\\Tests\\\\Cache\\\\BatchCacheTest::it_writes_to_cache_with_default_ttl#int value\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\Cache\\\\BatchCacheTest::it_writes_to_cache_with_default_ttl#callable\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\Cache\\\\BatchCacheTest::it_writes_to_cache_with_a_dateinterval_ttl\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\Cache\\\\BatchCacheTest::it_can_override_default_ttl\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ExportableTest::needs_to_have_a_file_name_when_downloading\":0.002,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ExportableTest::needs_to_have_a_file_name_when_storing\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ExportableTest::needs_to_have_a_file_name_when_queuing\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ExportableTest::responsable_needs_to_have_file_name_configured_inside_the_export\":0.001,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ExportableTest::is_responsable\":0.037,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ExportableTest::can_have_customized_header\":0.002,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ExportableTest::can_set_custom_headers_in_export_class\":0.001,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ExportableTest::can_get_raw_export_contents\":0.005,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ExportableTest::can_have_customized_disk_options_when_storing\":0.007,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ExportableTest::can_have_customized_disk_options_when_queueing\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ExportableTest::can_set_disk_options_in_export_class_when_storing\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ExportableTest::can_set_disk_options_in_export_class_when_queuing\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ExportableTest::can_override_export_class_disk_options_when_calling_store\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ExportableTest::can_override_export_class_disk_options_when_calling_queue\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ExportableTest::can_have_empty_disk_options_when_storing\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ExportableTest::can_have_empty_disk_options_when_queueing\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromArrayTest::can_export_from_array\":0.011,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromCollectionTest::can_export_from_collection\":0.036,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromCollectionTest::can_export_with_multiple_sheets_from_collection\":0.139,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromCollectionTest::can_export_from_lazy_collection\":0.007,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromGeneratorTest::can_export_from_generator\":0.007,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromIteratorTest::can_export_from_iterator\":0.007,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ImportableTest::can_import_a_simple_xlsx_file\":0.006,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ImportableTest::can_import_a_simple_xlsx_file_from_uploaded_file\":0.008,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ImportableTest::can_import_a_simple_csv_file_with_html_tags_inside\":0.006,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ImportableTest::can_import_a_simple_xlsx_file_with_ignore_empty_set_to_true\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ImportableTest::can_import_a_simple_xlsx_file_with_ignore_empty_set_to_false\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\OnEachRowTest::can_import_each_row_individually\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\OnEachRowTest::it_respects_the_end_column\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\RegistersEventListenersTest::events_get_called_when_exporting\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\RegistersEventListenersTest::events_get_called_when_importing\":0.01,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\RegistersEventListenersTest::can_have_invokable_class_as_listener\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\RemembersChunkOffsetTest::can_set_and_get_chunk_offset\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\RemembersChunkOffsetTest::can_access_chunk_offset_on_import_to_array_in_chunks\":0.249,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\RemembersRowNumberTest::can_set_and_get_row_number\":0.001,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\RemembersRowNumberTest::can_access_row_number_on_import_to_model\":0.185,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\RemembersRowNumberTest::can_access_row_number_on_import_to_array_in_chunks\":3.444,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\RemembersRowNumberTest::can_access_row_number_on_import_to_array_in_chunks_with_batch_inserts\":3.44,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\SkipsEmptyRowsTest::skips_empty_rows_when_importing_to_collection\":0.005,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\SkipsEmptyRowsTest::skips_empty_rows_when_importing_on_each_row\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\SkipsEmptyRowsTest::skips_empty_rows_when_importing_to_model\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\SkipsEmptyRowsTest::custom_skips_rows_when_importing_to_collection\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\SkipsEmptyRowsTest::custom_skips_rows_when_importing_to_model\":0.005,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\SkipsEmptyRowsTest::custom_skips_rows_when_using_oneachrow\":0.005,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ToArrayTest::can_import_to_array\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ToArrayTest::can_import_multiple_sheets_to_array\":0.005,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ToCollectionTest::can_import_to_collection\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ToCollectionTest::can_import_multiple_sheets_to_collection\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithBackgroundColorTest::can_configure_background_color_from_rgb_string\":0.007,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithBackgroundColorTest::can_configure_background_color_as_array\":0.006,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithBackgroundColorTest::can_configure_background_color_with_color_instance\":0.006,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCalculatedFormulasTest::by_default_does_not_calculate_formulas\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCalculatedFormulasTest::can_import_to_array_with_calculated_formulas\":0.005,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCalculatedFormulasTest::can_import_to_model_with_calculated_formulas\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCalculatedFormulasTest::can_import_to_array_with_calculated_formulas_and_multi_sheet_references\":0.006,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCalculatedFormulasTest::can_import_to_array_with_calculated_formulas_and_skips_empty\":0.018,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCalculatedFormulasTest::can_import_to_model_with_calculated_formulas_and_skips_empty\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithColumnFormattingTest::can_export_with_column_formatting\":0.008,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithColumnWidthsTest::can_set_column_width\":0.007,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCustomCsvSettingsTest::can_store_csv_export_with_custom_settings\":0.002,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCustomCsvSettingsTest::can_store_csv_export_with_custom_encoding\":0.001,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCustomCsvSettingsTest::can_read_csv_with_auto_detecting_delimiter_semicolon\":0.002,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCustomCsvSettingsTest::can_read_csv_with_auto_detecting_delimiter_comma\":0.002,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCustomCsvSettingsTest::can_read_csv_import_with_custom_settings\":0.003,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCustomCsvSettingsTest::cannot_read_with_wrong_delimiter\":0.002,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCustomStartCellTest::can_store_collection_with_custom_start_cell\":0.003,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCustomValueBinderTest::can_set_a_value_binder_on_export\":0.011,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCustomValueBinderTest::can_set_a_value_binder_on_import\":0.005,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithDefaultStylesTest::can_configure_default_styles\":0.007,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithEventsTest::export_events_get_called\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithEventsTest::import_events_get_called\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithEventsTest::import_chunked_events_get_called\":0.499,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithEventsTest::can_have_invokable_class_as_listener\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithEventsTest::can_have_global_event_listeners\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithEventsTest::can_have_custom_concern_handlers\":0.012,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithEventsTest::can_have_custom_sheet_concern_handlers\":0.011,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithFormatDataTest::by_default_import_to_array\":0.008,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithFormatDataTest::can_import_to_array_with_format_data\":0.007,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithFormatDataTest::can_import_to_array_with_format_data_and_skips_empty_rows\":0.006,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithFormatDataTest::by_default_import_to_collection\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithFormatDataTest::can_import_to_collection_with_format_data\":0.005,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithFormatDataTest::by_default_import_to_model\":0.006,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithFormatDataTest::can_import_to_model_with_format_data\":0.005,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithHeadingsTest::can_export_from_collection_with_heading_row\":0.007,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithHeadingsTest::can_export_from_collection_with_multiple_heading_rows\":0.021,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithHeadingsTest::can_export_from_collection_with_heading_row_with_custom_start_cell\":0.007,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMappingTest::can_export_with_heading\":0.007,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMappingTest::can_return_multiple_rows_in_map\":0.007,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMappingTest::json_array_columns_shouldnt_be_detected_as_multiple_rows\":0.007,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithPropertiesTest::can_set_custom_document_properties\":0.006,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithPropertiesTest::it_merges_with_default_properties\":0.006,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithPropertiesTest::it_ignores_empty_properties\":0.006,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithReadFilterTest::can_register_custom_read_filter\":0.003,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithStrictNullComparisonTest::exported_zero_values_are_not_null_when_exporting_with_strict_null_comparison\":0.007,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithStrictNullComparisonTest::exported_zero_values_are_null_when_not_exporting_with_strict_null_comparison\":0.006,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithStrictNullComparisonTest::exports_trailing_empty_cells\":0.003,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithStrictNullComparisonTest::exports_trailing_empty_cells_by_setting_config_strict_null_comparison\":0.003,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithStylesTest::can_configure_styles\":0.009,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithTitleTest::can_export_with_title\":0.007,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithTitleTest::can_export_sheet_title_when_longer_than_max_length\":0.006,\"Maatwebsite\\\\Excel\\\\Tests\\\\DelegatedMacroableTest::can_call_methods_from_delegate\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\DelegatedMacroableTest::can_use_writer_macros\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\DelegatedMacroableTest::can_use_sheet_macros\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelFakeTest::can_fake_an_export\":0.001,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelFakeTest::can_assert_against_a_fake_downloaded_export\":0.001,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelFakeTest::can_assert_against_a_fake_stored_export\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelFakeTest::can_assert_regex_against_a_fake_stored_export_with_multiple_files\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelFakeTest::a_callback_can_be_passed_as_the_second_argument_when_asserting_against_a_faked_stored_export\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelFakeTest::can_assert_against_a_fake_queued_export\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelFakeTest::can_assert_against_a_fake_implicitly_queued_export\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelFakeTest::can_assert_against_a_fake_queued_export_with_chain\":0.001,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelFakeTest::can_assert_against_a_fake_raw_export\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelFakeTest::can_assert_against_a_fake_import\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelFakeTest::can_assert_against_a_fake_import_with_uploaded_file\":0.001,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelFakeTest::can_assert_against_a_fake_queued_import\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelFakeTest::can_assert_against_a_fake_implicitly_queued_import\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelFakeTest::can_assert_against_a_fake_queued_import_with_chain\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelFakeTest::a_callback_can_be_passed_as_the_second_argument_when_asserting_against_a_faked_queued_export\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelServiceProviderTest::custom_transaction_handler_is_bound\":0.001,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelServiceProviderTest::is_bound\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelServiceProviderTest::has_aliased\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelServiceProviderTest::registers_console_commands\":0.006,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelServiceProviderTest::sets_php_spreadsheet_settings\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::can_download_an_export_object_with_facade\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::can_download_an_export_object\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::can_store_an_export_object_on_default_disk\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::can_store_an_export_object_on_another_disk\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::can_store_csv_export_with_default_settings\":0.001,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::can_get_raw_export_contents\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::can_store_tsv_export_with_default_settings\":0.001,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::can_store_csv_export_with_custom_settings\":0.001,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::cannot_use_from_collection_and_from_view_on_same_export\":0.001,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::can_import_a_simple_xlsx_file_to_array\":0.003,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::can_import_a_simple_xlsx_file_to_collection\":0.039,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::can_import_a_simple_xlsx_file_to_collection_without_import_object\":0.031,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::can_import_a_simple_xlsx_file\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::can_import_a_tsv_file\":0.005,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::can_chain_imports\":0.006,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::can_import_a_simple_xlsx_file_from_uploaded_file\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::can_import_a_simple_xlsx_file_from_real_path\":0.003,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::import_will_throw_error_when_no_reader_type_could_be_detected_when_no_extension\":0.001,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::import_will_throw_error_when_no_reader_type_could_be_detected_with_unknown_extension\":0.013,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::can_import_without_extension_with_explicit_reader_type\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\HeadingRowImportTest::can_import_only_heading_row\":0.059,\"Maatwebsite\\\\Excel\\\\Tests\\\\HeadingRowImportTest::can_import_only_heading_row_with_custom_heading_row_formatter\":0.003,\"Maatwebsite\\\\Excel\\\\Tests\\\\HeadingRowImportTest::can_import_only_heading_row_with_custom_heading_row_formatter_with_key\":0.003,\"Maatwebsite\\\\Excel\\\\Tests\\\\HeadingRowImportTest::can_import_only_heading_row_with_custom_row_number\":0.008,\"Maatwebsite\\\\Excel\\\\Tests\\\\HeadingRowImportTest::can_import_only_heading_row_for_multiple_sheets\":0.003,\"Maatwebsite\\\\Excel\\\\Tests\\\\HeadingRowImportTest::can_import_only_heading_row_for_multiple_sheets_with_key\":0.003,\"Maatwebsite\\\\Excel\\\\Tests\\\\HeadingRowImportTest::can_import_only_heading_row_for_multiple_sheets_with_custom_row_number\":0.003,\"Maatwebsite\\\\Excel\\\\Tests\\\\HeadingRowImportTest::can_import_heading_row_with_custom_formatter_defined_in_config\":0.003,\"Maatwebsite\\\\Excel\\\\Tests\\\\InteractsWithQueueTest::read_chunk_job_can_interact_with_queue\":0.001,\"Maatwebsite\\\\Excel\\\\Tests\\\\InteractsWithQueueTest::append_data_to_sheet_job_can_interact_with_queue\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\InteractsWithQueueTest::append_query_to_sheet_job_can_interact_with_queue\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\InteractsWithQueueTest::append_view_to_sheet_job_can_interact_with_queue\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\DownloadCollectionTest::can_download_a_collection_as_excel\":0.008,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\DownloadCollectionTest::can_download_a_collection_with_headers_as_excel\":0.009,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\DownloadCollectionTest::can_download_collection_with_headers_with_hidden_eloquent_attributes\":0.007,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\DownloadCollectionTest::can_download_collection_with_headers_when_making_attributes_visible\":0.007,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\DownloadCollectionTest::can_set_custom_response_headers\":0.005,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\StoreCollectionTest::can_store_a_collection_as_excel\":0.011,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\StoreCollectionTest::can_store_a_collection_as_excel_on_non_default_disk\":0.006,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\StoreCollectionTest::can_store_a_collection_with_headings_as_excel\":0.007,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\StoreCollectionTest::can_store_a_model_collection_with_headings_as_excel\":0.008,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedExportTest::can_queue_an_export_and_store_on_different_disk\":0.234,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedExportTest::can_queue_export_with_remote_temp_disk\":0.276,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedExportTest::can_queue_export_with_remote_temp_disk_and_prefix\":0.24,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedExportTest::can_implicitly_queue_an_export\":0.241,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedExportTest::can_queue_export_with_mapping_on_eloquent_models\":0.017,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedExportTest::can_catch_failures\":0.007,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedExportTest::can_catch_failures_on_queue_export_job\":0.003,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedExportTest::can_set_locale_on_queue_export_job\":0.015,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedExportTest::can_queue_export_not_flushing_the_cache\":0.294,\"Maatwebsite\\\\Excel\\\\Tests\\\\TemporaryFileTest::can_use_default_rights\":0.001,\"Maatwebsite\\\\Excel\\\\Tests\\\\TemporaryFileTest::can_use_dir_rights\":0.001,\"Maatwebsite\\\\Excel\\\\Tests\\\\TemporaryFileTest::can_use_file_rights\":0.001,\"ShouldQueueWithoutChainTest::can_import_to_model_in_chunks\":0.065,\"ShouldQueueWithoutChainTest::can_import_to_model_without_job_chaining\":0.053,\"ShouldQueueWithoutChainTest::a_queue_name_can_be_specified_when_importing\":0.045,\"ShouldQueueWithoutChainTest::the_cleanup_only_runs_when_all_jobs_are_done\":0.067,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\SkipsOnErrorTest::can_skip_on_error\":0.039,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\SkipsOnErrorTest::can_skip_errors_and_collect_all_errors_at_the_end\":0.036,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\SkipsOnFailureTest::can_skip_on_error\":0.037,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\SkipsOnFailureTest::skips_only_failed_rows_in_batch\":0.029,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\SkipsOnFailureTest::can_skip_failures_and_collect_all_failures_at_the_end\":0.028,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\SkipsOnFailureTest::can_validate_using_oneachrow_and_skipsonfailure\":0.028,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\SkipsOnFailureTest::can_validate_using_tocollection_and_skipsonfailure\":0.028,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ToModelTest::can_import_each_row_to_model\":0.058,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ToModelTest::has_timestamps_when_imported_single_model\":0.052,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ToModelTest::can_import_multiple_models_in_single_to_model\":0.06,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ToModelTest::can_import_multiple_different_types_of_models_in_single_to_model\":0.063,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithBatchInsertsTest::can_import_to_model_in_batches\":0.074,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithBatchInsertsTest::can_import_to_model_in_batches_bigger_file\":0.278,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithBatchInsertsTest::can_import_multiple_different_types_of_models_in_single_to_model\":0.054,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithBatchInsertsTest::has_timestamps_when_imported_in_batches\":0.056,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithChunkReadingTest::can_import_to_model_in_chunks_un\":0.065,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithChunkReadingTest::can_import_to_model_in_chunks_and_insert_in_batches\":0.436,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithChunkReadingTest::can_import_to_model_in_chunks_and_insert_in_batches_with_heading_row\":0.429,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithChunkReadingTest::can_import_csv_in_chunks_and_insert_in_batches\":1.206,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithChunkReadingTest::can_import_to_model_in_chunks_and_insert_in_batches_with_multiple_sheets\":1.223,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithChunkReadingTest::can_import_to_array_in_chunks\":1.854,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithChunkReadingTest::can_import_to_model_in_chunks_and_insert_in_batches_with_multiple_sheets_objects_by_index\":1.216,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithChunkReadingTest::can_import_to_model_in_chunks_and_insert_in_batches_with_multiple_sheets_objects_by_name\":1.211,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithChunkReadingTest::can_catch_job_failed_in_chunks\":0.048,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithChunkReadingTest::can_import_to_array_and_format_in_chunks\":0.054,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithChunkReadingTest::can_import_to_array_in_chunks_without_formatting\":0.048,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithColumnLimitTest::can_import_to_array_with_column_limit\":0.026,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithColumnLimitTest::can_import_to_array_with_column_limit_and_skips_empty_rows\":0.033,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithGroupedHeadingRowTest::can_import_to_array_with_grouped_headers\":0.055,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithGroupedHeadingRowTest::can_import_oneachrow_with_grouped_headers\":0.053,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithGroupedHeadingRowTest::can_import_to_collection_with_grouped_headers\":0.05,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithGroupedHeadingRowTest::can_import_each_row_to_model_with_grouped_headers\":0.061,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithHeadingRowTest::can_import_each_row_to_model_with_heading_row\":0.029,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithHeadingRowTest::can_import_each_row_to_model_with_different_heading_row\":0.03,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithHeadingRowTest::can_import_to_array_with_heading_row\":0.028,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithHeadingRowTest::can_import_empty_rows_with_header\":0.029,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithHeadingRowTest::can_import_empty_models_with_header\":0.03,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithHeadingRowTest::can_cast_empty_headers_to_indexed_int\":0.028,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithLimitTest::can_import_a_limited_section_of_rows_to_model_with_different_start_row\":0.057,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithLimitTest::can_import_to_array_with_limit\":0.03,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithLimitTest::can_set_limit_bigger_than_row_size\":0.028,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMappedCellsTest::can_import_with_references_to_cells\":0.034,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMappedCellsTest::can_import_with_nested_references_to_cells\":0.031,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMappedCellsTest::can_import_with_references_to_cells_to_model\":0.041,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithStartRowTest::can_import_each_row_to_model_with_different_start_row\":0.027,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithStartRowTest::can_import_to_array_with_start_row\":0.027,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithUpsertsTest::can_upsert_models_in_batches\":0.03,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithUpsertsTest::can_upsert_models_in_rows\":0.03,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithUpsertsTest::can_upsert_models_in_batches_with_defined_upsert_columns\":0.03,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithUpsertsTest::can_upsert_models_in_rows_with_defined_upsert_columns\":0.029,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::can_validate_rows\":0.068,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::can_validate_rows_with_closure_validation_rules\":0.054,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::can_validate_rows_with_custom_validation_rule_objects\":0.07,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::can_validate_rows_with_conditionality\":0.053,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::can_validate_rows_with_unless_conditionality\":0.056,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::can_validate_rows_with_combined_rules_with_colons\":0.067,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::can_validate_with_custom_attributes\":0.049,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::can_validate_with_custom_message\":0.051,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::can_validate_rows_with_headings\":0.049,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::can_validate_rows_with_grouped_headings\":0.049,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::can_validate_rows_in_batches\":0.052,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::can_validate_using_oneachrow\":0.05,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::can_validate_using_collection\":0.053,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::can_validate_using_array\":0.129,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::can_configure_validator\":0.059,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::can_prepare_using_toarray\":0.057,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::can_prepare_using_tocollection\":0.051,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::can_prepare_using_tomodel\":0.053,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::can_prepare_using_oneachrow\":0.052,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::can_prepare_using_skipsemptyrows\":0.06,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedImportTest::cannot_queue_import_that_does_not_implement_should_queue\":0.053,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedImportTest::can_queue_an_import\":2.07,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedImportTest::can_queue_an_import_with_batch_cache_and_file_store\":2.129,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedImportTest::can_queue_import_with_remote_temp_disk\":2.209,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedImportTest::can_keep_extension_for_temp_file_on_remote_disk\":2.125,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedImportTest::can_queue_import_with_remote_temp_disk_and_prefix\":2.08,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedImportTest::can_automatically_delete_temp_file_on_failure_when_using_remote_disk\":0.106,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedImportTest::cannot_automatically_delete_temp_file_on_failure_when_using_local_disk\":0.12,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedImportTest::can_force_remote_download_and_deletion_for_each_chunk_on_queue\":2.13,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedImportTest::can_define_middleware_method_on_queued_import\":0.065,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedImportTest::can_define_retry_until_method_on_queued_import\":0.064,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedImportTest::can_define_max_exceptions_property_on_queued_import\":0.105,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromQueryTest::can_export_from_query\":0.116,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromQueryTest::can_export_from_relation_query_queued\":0.181,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromQueryTest::can_export_from_query_with_eager_loads\":0.085,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromQueryTest::can_export_from_query_with_eager_loads_and_queued\":0.106,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromQueryTest::can_export_from_query_builder_without_using_eloquent\":0.063,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromQueryTest::can_export_from_query_builder_without_using_eloquent_and_queued\":0.149,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromQueryTest::can_export_from_query_builder_with_nested_arrays\":0.069,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromQueryTest::can_export_from_query_builder_with_nested_arrays_queued\":0.079,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromQueryTest::can_export_from_query_with_batch_caching\":0.114,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromQueryTest::can_export_from_query_with_prepare_rows\":0.123,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromQueryTest::can_export_from_scout\":0.117,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromViewTest::can_export_from_view\":0.041,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromViewTest::can_export_multiple_sheets_from_view\":0.094,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithConditionalSheetsTest::can_select_which_sheets_will_be_imported\":0.013,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCustomQuerySizeTest::can_export_with_custom_count\":0.09,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMultipleSheetsTest::can_export_with_multiple_sheets_using_collections\":0.151,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMultipleSheetsTest::can_export_multiple_sheets_from_view\":0.11,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMultipleSheetsTest::unknown_sheet_index_will_throw_sheet_not_found_exception\":0.005,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMultipleSheetsTest::unknown_sheet_name_will_throw_sheet_not_found_exception\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMultipleSheetsTest::unknown_sheet_name_can_be_ignored\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMultipleSheetsTest::unknown_sheet_indices_can_be_ignored_per_name\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMultipleSheetsTest::unknown_sheet_indices_can_be_ignored\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMultipleSheetsTest::unknown_sheet_indices_can_be_ignored_per_sheet\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMultipleSheetsTest::can_import_multiple_sheets\":0.013,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMultipleSheetsTest::can_import_multiple_sheets_by_sheet_name\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMultipleSheetsTest::can_import_multiple_sheets_by_sheet_index_and_name\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMultipleSheetsTest::can_import_multiple_sheets_by_sheet_name_and_index\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedQueryExportTest::can_queue_an_export\":0.208,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedQueryExportTest::can_queue_an_export_with_batch_cache_and_file_store\":0.262,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedQueryExportTest::can_queue_an_export_with_mapping\":0.049,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedQueryExportTest::can_queue_scout_export\":0.228,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedViewExportTest::can_queue_an_export\":0.145,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedViewExportTest::can_export_multiple_sheets_from_view\":0.26,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromCollectionTest::can_export_from_lazy_collection_with_queue\":0.026,\"Maatwebsite\\\\Excel\\\\Tests\\\\CellTest::can_get_cell_value\":0.029,\"Maatwebsite\\\\Excel\\\\Tests\\\\CellTest::can_trim_empty_cells\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\CellTest::convert_empty_cells_to_null\":0.003,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithEventsTest::export_chunked_events_get_called\":0.113,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\ImportAsMacroTest::can_import_directly_into_a_model_with_mapping\":0.036,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\ImportMacroTest::can_import_directly_into_a_model\":0.036,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\DownloadQueryMacroTest::can_download_a_query_as_excel\":0.062,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\DownloadQueryMacroTest::can_download_a_collection_with_headers_as_excel\":0.061,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\StoreQueryMacroTest::can_download_a_query_as_excel\":0.063,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\StoreQueryMacroTest::can_download_a_query_as_excel_on_different_disk\":0.061,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\StoreQueryMacroTest::can_store_a_query_with_headers_as_excel\":0.07,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ToModelTest::can_import_models_with_belongs_to_relations\":0.067,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ToModelTest::can_import_models_with_belongs_to_many_relations\":0.07,\"Maatwebsite\\\\Excel\\\\Tests\\\\HeadingRowImportTest::test_can_import_only_heading_row\":0.005,\"Maatwebsite\\\\Excel\\\\Tests\\\\Cache\\\\BatchCacheTest::test_will_get_multiple_from_memory_if_cells_hold_in_memory\":0.032,\"Maatwebsite\\\\Excel\\\\Tests\\\\Cache\\\\BatchCacheTest::test_will_get_multiple_from_cache_if_cells_are_persisted\":0.001,\"Maatwebsite\\\\Excel\\\\Tests\\\\Cache\\\\BatchCacheTest::test_will_get_multiple_from_cache_and_persisted\":0.001,\"Maatwebsite\\\\Excel\\\\Tests\\\\Cache\\\\BatchCacheTest::test_it_persists_to_cache_when_memory_limit_reached_on_setting_a_value\":0.001,\"Maatwebsite\\\\Excel\\\\Tests\\\\Cache\\\\BatchCacheTest::test_it_persists_to_cache_when_memory_limit_reached_on_setting_multiple_values\":0.001,\"Maatwebsite\\\\Excel\\\\Tests\\\\Cache\\\\BatchCacheTest::test_it_writes_to_cache_with_default_ttl#null (forever)\":0.002,\"Maatwebsite\\\\Excel\\\\Tests\\\\Cache\\\\BatchCacheTest::test_it_writes_to_cache_with_default_ttl#int value\":0.001,\"Maatwebsite\\\\Excel\\\\Tests\\\\Cache\\\\BatchCacheTest::test_it_writes_to_cache_with_default_ttl#callable\":0.001,\"Maatwebsite\\\\Excel\\\\Tests\\\\Cache\\\\BatchCacheTest::test_it_writes_to_cache_with_a_dateinterval_ttl\":0.001,\"Maatwebsite\\\\Excel\\\\Tests\\\\Cache\\\\BatchCacheTest::test_it_can_override_default_ttl\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\CellTest::test_can_get_cell_value\":0.043,\"Maatwebsite\\\\Excel\\\\Tests\\\\CellTest::test_can_trim_empty_cells\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\CellTest::test_convert_empty_cells_to_null\":0.005,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ExportableTest::test_needs_to_have_a_file_name_when_downloading\":0.001,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ExportableTest::test_needs_to_have_a_file_name_when_storing\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ExportableTest::test_needs_to_have_a_file_name_when_queuing\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ExportableTest::test_responsable_needs_to_have_file_name_configured_inside_the_export\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ExportableTest::test_is_responsable\":0.037,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ExportableTest::test_can_have_customized_header\":0.002,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ExportableTest::test_can_set_custom_headers_in_export_class\":0.002,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ExportableTest::test_can_get_raw_export_contents\":0.008,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ExportableTest::test_can_have_customized_disk_options_when_storing\":0.005,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ExportableTest::test_can_have_customized_disk_options_when_queueing\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ExportableTest::test_can_set_disk_options_in_export_class_when_storing\":0.001,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ExportableTest::test_can_set_disk_options_in_export_class_when_queuing\":0.001,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ExportableTest::test_can_override_export_class_disk_options_when_calling_store\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ExportableTest::test_can_override_export_class_disk_options_when_calling_queue\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ExportableTest::test_can_have_empty_disk_options_when_storing\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ExportableTest::test_can_have_empty_disk_options_when_queueing\":0.001,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromArrayTest::test_can_export_from_array\":0.029,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromCollectionTest::test_can_export_from_collection\":0.049,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromCollectionTest::test_can_export_with_multiple_sheets_from_collection\":0.196,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromCollectionTest::test_can_export_from_lazy_collection\":0.01,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromCollectionTest::test_can_export_from_lazy_collection_with_queue\":0.04,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromGeneratorTest::test_can_export_from_generator\":0.01,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromIteratorTest::test_can_export_from_iterator\":0.01,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromQueryTest::test_can_export_from_query\":0.115,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromQueryTest::test_can_export_from_relation_query_queued\":0.183,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromQueryTest::test_can_export_from_query_with_eager_loads\":0.085,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromQueryTest::test_can_export_from_query_with_eager_loads_and_queued\":0.106,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromQueryTest::test_can_export_from_query_builder_without_using_eloquent\":0.07,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromQueryTest::test_can_export_from_query_builder_without_using_eloquent_and_queued\":0.149,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromQueryTest::test_can_export_from_query_builder_with_nested_arrays\":0.07,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromQueryTest::test_can_export_from_query_builder_with_nested_arrays_queued\":0.09,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromQueryTest::test_can_export_from_query_with_batch_caching\":0.116,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromQueryTest::test_can_export_from_query_with_prepare_rows\":0.117,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromQueryTest::test_can_export_from_scout\":0.144,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromViewTest::test_can_export_from_view\":0.04,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\FromViewTest::test_can_export_multiple_sheets_from_view\":0.101,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ImportableTest::test_can_import_a_simple_xlsx_file\":0.008,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ImportableTest::test_can_import_a_simple_xlsx_file_from_uploaded_file\":0.01,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ImportableTest::test_can_import_a_simple_csv_file_with_html_tags_inside\":0.011,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ImportableTest::test_can_import_a_simple_xlsx_file_with_ignore_empty_set_to_true\":0.005,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ImportableTest::test_can_import_a_simple_xlsx_file_with_ignore_empty_set_to_false\":0.005,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\OnEachRowTest::test_can_import_each_row_individually\":0.007,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\OnEachRowTest::test_it_respects_the_end_column\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\RegistersEventListenersTest::test_events_get_called_when_exporting\":0.016,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\RegistersEventListenersTest::test_events_get_called_when_importing\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\RegistersEventListenersTest::test_can_have_invokable_class_as_listener\":0.01,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\RemembersChunkOffsetTest::test_can_set_and_get_chunk_offset\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\RemembersChunkOffsetTest::test_can_access_chunk_offset_on_import_to_array_in_chunks\":0.121,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\RemembersRowNumberTest::test_can_set_and_get_row_number\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\RemembersRowNumberTest::test_can_access_row_number_on_import_to_model\":0.145,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\RemembersRowNumberTest::test_can_access_row_number_on_import_to_array_in_chunks\":0.086,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\RemembersRowNumberTest::test_can_access_row_number_on_import_to_array_in_chunks_with_batch_inserts\":0.078,\"ShouldQueueWithoutChainTest::test_can_import_to_model_in_chunks\":0.065,\"ShouldQueueWithoutChainTest::test_can_import_to_model_without_job_chaining\":0.046,\"ShouldQueueWithoutChainTest::test_a_queue_name_can_be_specified_when_importing\":0.051,\"ShouldQueueWithoutChainTest::test_the_cleanup_only_runs_when_all_jobs_are_done\":0.061,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\SkipsEmptyRowsTest::test_skips_empty_rows_when_importing_to_collection\":0.006,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\SkipsEmptyRowsTest::test_skips_empty_rows_when_importing_on_each_row\":0.003,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\SkipsEmptyRowsTest::test_skips_empty_rows_when_importing_to_model\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\SkipsEmptyRowsTest::test_custom_skips_rows_when_importing_to_collection\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\SkipsEmptyRowsTest::test_custom_skips_rows_when_importing_to_model\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\SkipsEmptyRowsTest::test_custom_skips_rows_when_using_oneachrow\":0.005,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\SkipsOnErrorTest::test_can_skip_on_error\":0.042,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\SkipsOnErrorTest::test_can_skip_errors_and_collect_all_errors_at_the_end\":0.037,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\SkipsOnFailureTest::test_can_skip_on_error\":0.038,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\SkipsOnFailureTest::test_skips_only_failed_rows_in_batch\":0.027,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\SkipsOnFailureTest::test_can_skip_failures_and_collect_all_failures_at_the_end\":0.028,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\SkipsOnFailureTest::test_can_validate_using_oneachrow_and_skipsonfailure\":0.028,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\SkipsOnFailureTest::test_can_validate_using_tocollection_and_skipsonfailure\":0.028,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ToArrayTest::test_can_import_to_array\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ToArrayTest::test_can_import_multiple_sheets_to_array\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ToCollectionTest::test_can_import_to_collection\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ToCollectionTest::test_can_import_multiple_sheets_to_collection\":0.003,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ToModelTest::test_can_import_each_row_to_model\":0.064,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ToModelTest::test_has_timestamps_when_imported_single_model\":0.055,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ToModelTest::test_can_import_multiple_models_in_single_to_model\":0.059,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ToModelTest::test_can_import_multiple_different_types_of_models_in_single_to_model\":0.055,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ToModelTest::test_can_import_models_with_belongs_to_relations\":0.068,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ToModelTest::test_can_import_models_with_belongs_to_many_relations\":0.076,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithBackgroundColorTest::test_can_configure_background_color_from_rgb_string\":0.017,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithBackgroundColorTest::test_can_configure_background_color_as_array\":0.009,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithBackgroundColorTest::test_can_configure_background_color_with_color_instance\":0.011,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithBatchInsertsTest::test_can_import_to_model_in_batches\":0.059,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithBatchInsertsTest::test_can_import_to_model_in_batches_bigger_file\":0.278,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithBatchInsertsTest::test_can_import_multiple_different_types_of_models_in_single_to_model\":0.054,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithBatchInsertsTest::test_has_timestamps_when_imported_in_batches\":0.058,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCalculatedFormulasTest::test_by_default_does_not_calculate_formulas\":0.007,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCalculatedFormulasTest::test_can_import_to_array_with_calculated_formulas\":0.006,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCalculatedFormulasTest::test_can_import_to_model_with_calculated_formulas\":0.006,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCalculatedFormulasTest::test_can_import_to_array_with_calculated_formulas_and_multi_sheet_references\":0.009,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCalculatedFormulasTest::test_can_import_to_array_with_calculated_formulas_and_skips_empty\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCalculatedFormulasTest::test_can_import_to_model_with_calculated_formulas_and_skips_empty\":0.005,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithChunkReadingTest::test_can_import_to_model_in_chunks_un\":0.064,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithChunkReadingTest::test_can_import_to_model_in_chunks_and_insert_in_batches\":0.438,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithChunkReadingTest::test_can_import_to_model_in_chunks_and_insert_in_batches_with_heading_row\":0.441,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithChunkReadingTest::test_can_import_csv_in_chunks_and_insert_in_batches\":1.218,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithChunkReadingTest::test_can_import_to_model_in_chunks_and_insert_in_batches_with_multiple_sheets\":1.254,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithChunkReadingTest::test_can_import_to_array_in_chunks\":1.882,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithChunkReadingTest::test_can_import_to_model_in_chunks_and_insert_in_batches_with_multiple_sheets_objects_by_index\":1.222,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithChunkReadingTest::test_can_import_to_model_in_chunks_and_insert_in_batches_with_multiple_sheets_objects_by_name\":1.219,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithChunkReadingTest::test_can_catch_job_failed_in_chunks\":0.048,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithChunkReadingTest::test_can_import_to_array_and_format_in_chunks\":0.051,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithChunkReadingTest::test_can_import_to_array_in_chunks_without_formatting\":0.088,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithColumnFormattingTest::test_can_export_with_column_formatting\":0.018,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithColumnLimitTest::test_can_import_to_array_with_column_limit\":0.026,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithColumnLimitTest::test_can_import_to_array_with_column_limit_and_skips_empty_rows\":0.032,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithColumnWidthsTest::test_can_set_column_width\":0.016,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithConditionalSheetsTest::test_can_select_which_sheets_will_be_imported\":0.013,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCustomCsvSettingsTest::test_can_store_csv_export_with_custom_settings\":0.003,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCustomCsvSettingsTest::test_can_store_csv_export_with_custom_encoding\":0.003,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCustomCsvSettingsTest::test_can_read_csv_with_auto_detecting_delimiter_semicolon\":0.005,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCustomCsvSettingsTest::test_can_read_csv_with_auto_detecting_delimiter_comma\":0.003,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCustomCsvSettingsTest::test_can_read_csv_import_with_custom_settings\":0.003,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCustomCsvSettingsTest::test_cannot_read_with_wrong_delimiter\":0.003,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCustomQuerySizeTest::test_can_export_with_custom_count\":0.09,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCustomStartCellTest::test_can_store_collection_with_custom_start_cell\":0.005,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCustomValueBinderTest::test_can_set_a_value_binder_on_export\":0.017,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithCustomValueBinderTest::test_can_set_a_value_binder_on_import\":0.005,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithDefaultStylesTest::test_can_configure_default_styles\":0.015,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithEventsTest::test_export_events_get_called\":0.011,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithEventsTest::test_import_events_get_called\":0.005,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithEventsTest::test_import_chunked_events_get_called\":0.093,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithEventsTest::test_can_have_invokable_class_as_listener\":0.01,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithEventsTest::test_can_have_global_event_listeners\":0.009,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithEventsTest::test_can_have_custom_concern_handlers\":0.036,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithEventsTest::test_can_have_custom_sheet_concern_handlers\":0.019,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithEventsTest::test_export_chunked_events_get_called\":0.002,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithFormatDataTest::test_by_default_import_to_array\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithFormatDataTest::test_can_import_to_array_with_format_data\":0.006,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithFormatDataTest::test_can_import_to_array_with_format_data_and_skips_empty_rows\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithFormatDataTest::test_by_default_import_to_collection\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithFormatDataTest::test_can_import_to_collection_with_format_data\":0.005,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithFormatDataTest::test_by_default_import_to_model\":0.005,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithFormatDataTest::test_can_import_to_model_with_format_data\":0.005,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithGroupedHeadingRowTest::test_can_import_to_array_with_grouped_headers\":0.049,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithGroupedHeadingRowTest::test_can_import_oneachrow_with_grouped_headers\":0.047,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithGroupedHeadingRowTest::test_can_import_to_collection_with_grouped_headers\":0.049,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithGroupedHeadingRowTest::test_can_import_each_row_to_model_with_grouped_headers\":0.068,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithHeadingRowTest::test_can_import_each_row_to_model_with_heading_row\":0.029,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithHeadingRowTest::test_can_import_each_row_to_model_with_different_heading_row\":0.032,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithHeadingRowTest::test_can_import_to_array_with_heading_row\":0.026,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithHeadingRowTest::test_can_import_empty_rows_with_header\":0.03,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithHeadingRowTest::test_can_import_empty_models_with_header\":0.029,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithHeadingRowTest::test_can_cast_empty_headers_to_indexed_int\":0.025,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithHeadingsTest::test_can_export_from_collection_with_heading_row\":0.017,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithHeadingsTest::test_can_export_from_collection_with_multiple_heading_rows\":0.011,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithHeadingsTest::test_can_export_from_collection_with_heading_row_with_custom_start_cell\":0.01,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithLimitTest::test_can_import_a_limited_section_of_rows_to_model_with_different_start_row\":0.033,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithLimitTest::test_can_import_to_array_with_limit\":0.026,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithLimitTest::test_can_set_limit_bigger_than_row_size\":0.025,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMappedCellsTest::test_can_import_with_references_to_cells\":0.026,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMappedCellsTest::test_can_import_with_nested_references_to_cells\":0.026,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMappedCellsTest::test_can_import_with_references_to_cells_to_model\":0.028,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMappingTest::test_can_export_with_heading\":0.018,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMappingTest::test_can_return_multiple_rows_in_map\":0.017,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMappingTest::test_json_array_columns_shouldnt_be_detected_as_multiple_rows\":0.011,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMultipleSheetsTest::test_can_export_with_multiple_sheets_using_collections\":0.143,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMultipleSheetsTest::test_can_export_multiple_sheets_from_view\":0.11,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMultipleSheetsTest::test_unknown_sheet_index_will_throw_sheet_not_found_exception\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMultipleSheetsTest::test_unknown_sheet_name_will_throw_sheet_not_found_exception\":0.003,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMultipleSheetsTest::test_unknown_sheet_name_can_be_ignored\":0.003,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMultipleSheetsTest::test_unknown_sheet_indices_can_be_ignored_per_name\":0.003,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMultipleSheetsTest::test_unknown_sheet_indices_can_be_ignored\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMultipleSheetsTest::test_unknown_sheet_indices_can_be_ignored_per_sheet\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMultipleSheetsTest::test_can_import_multiple_sheets\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMultipleSheetsTest::test_can_import_multiple_sheets_by_sheet_name\":0.013,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMultipleSheetsTest::test_can_import_multiple_sheets_by_sheet_index_and_name\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithMultipleSheetsTest::test_can_import_multiple_sheets_by_sheet_name_and_index\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithPropertiesTest::test_can_set_custom_document_properties\":0.009,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithPropertiesTest::test_it_merges_with_default_properties\":0.009,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithPropertiesTest::test_it_ignores_empty_properties\":0.011,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithReadFilterTest::test_can_register_custom_read_filter\":0.006,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithStartRowTest::test_can_import_each_row_to_model_with_different_start_row\":0.027,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithStartRowTest::test_can_import_to_array_with_start_row\":0.04,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithStrictNullComparisonTest::test_exported_zero_values_are_not_null_when_exporting_with_strict_null_comparison\":0.015,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithStrictNullComparisonTest::test_exported_zero_values_are_null_when_not_exporting_with_strict_null_comparison\":0.012,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithStrictNullComparisonTest::test_exports_trailing_empty_cells\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithStrictNullComparisonTest::test_exports_trailing_empty_cells_by_setting_config_strict_null_comparison\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithStylesTest::test_can_configure_styles\":0.017,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithTitleTest::test_can_export_with_title\":0.01,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithTitleTest::test_can_export_sheet_title_when_longer_than_max_length\":0.011,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithUpsertsTest::test_can_upsert_models_in_batches\":0.029,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithUpsertsTest::test_can_upsert_models_in_rows\":0.041,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithUpsertsTest::test_can_upsert_models_in_batches_with_defined_upsert_columns\":0.029,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithUpsertsTest::test_can_upsert_models_in_rows_with_defined_upsert_columns\":0.028,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::test_can_validate_rows\":0.051,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::test_can_validate_rows_with_closure_validation_rules\":0.051,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::test_can_validate_rows_with_custom_validation_rule_objects\":0.052,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::test_can_validate_rows_with_conditionality\":0.049,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::test_can_validate_rows_with_unless_conditionality\":0.052,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::test_can_validate_rows_with_combined_rules_with_colons\":0.069,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::test_can_validate_with_custom_attributes\":0.049,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::test_can_validate_with_custom_message\":0.051,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::test_can_validate_rows_with_headings\":0.055,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::test_can_validate_rows_with_grouped_headings\":0.049,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::test_can_validate_rows_in_batches\":0.05,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::test_can_validate_using_oneachrow\":0.051,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::test_can_validate_using_collection\":0.051,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::test_can_validate_using_array\":0.048,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::test_can_configure_validator\":0.057,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::test_can_prepare_using_toarray\":0.05,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::test_can_prepare_using_tocollection\":0.051,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::test_can_prepare_using_tomodel\":0.051,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::test_can_prepare_using_oneachrow\":0.05,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\WithValidationTest::test_can_prepare_using_skipsemptyrows\":0.049,\"Maatwebsite\\\\Excel\\\\Tests\\\\DelegatedMacroableTest::test_can_call_methods_from_delegate\":0.009,\"Maatwebsite\\\\Excel\\\\Tests\\\\DelegatedMacroableTest::test_can_use_writer_macros\":0.01,\"Maatwebsite\\\\Excel\\\\Tests\\\\DelegatedMacroableTest::test_can_use_sheet_macros\":0.008,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelFakeTest::test_can_fake_an_export\":0.001,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelFakeTest::test_can_assert_against_a_fake_downloaded_export\":0.001,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelFakeTest::test_can_assert_against_a_fake_stored_export\":0.001,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelFakeTest::test_can_assert_regex_against_a_fake_stored_export_with_multiple_files\":0.001,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelFakeTest::test_a_callback_can_be_passed_as_the_second_argument_when_asserting_against_a_faked_stored_export\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelFakeTest::test_can_assert_against_a_fake_queued_export\":0.001,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelFakeTest::test_can_assert_against_a_fake_implicitly_queued_export\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelFakeTest::test_can_assert_against_a_fake_queued_export_with_chain\":0.001,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelFakeTest::test_can_assert_against_a_fake_raw_export\":0.001,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelFakeTest::test_can_assert_against_a_fake_import\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelFakeTest::test_can_assert_against_a_fake_import_with_uploaded_file\":0.001,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelFakeTest::test_can_assert_against_a_fake_queued_import\":0.001,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelFakeTest::test_can_assert_against_a_fake_implicitly_queued_import\":0.001,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelFakeTest::test_can_assert_against_a_fake_queued_import_with_chain\":0.001,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelFakeTest::test_a_callback_can_be_passed_as_the_second_argument_when_asserting_against_a_faked_queued_export\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelServiceProviderTest::test_custom_transaction_handler_is_bound\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelServiceProviderTest::test_is_bound\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelServiceProviderTest::test_has_aliased\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelServiceProviderTest::test_registers_console_commands\":0.008,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelServiceProviderTest::test_sets_php_spreadsheet_settings\":0.001,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::test_can_download_an_export_object_with_facade\":0.008,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::test_can_download_an_export_object\":0.007,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::test_can_store_an_export_object_on_default_disk\":0.01,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::test_can_store_an_export_object_on_another_disk\":0.012,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::test_can_store_csv_export_with_default_settings\":0.001,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::test_can_get_raw_export_contents\":0.012,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::test_can_store_tsv_export_with_default_settings\":0.002,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::test_can_store_csv_export_with_custom_settings\":0.002,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::test_cannot_use_from_collection_and_from_view_on_same_export\":0.002,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::test_can_import_a_simple_xlsx_file_to_array\":0.003,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::test_can_import_a_simple_xlsx_file_to_collection\":0.003,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::test_can_import_a_simple_xlsx_file_to_collection_without_import_object\":0.003,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::test_can_import_a_simple_xlsx_file\":0.003,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::test_can_import_a_tsv_file\":0.009,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::test_can_chain_imports\":0.003,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::test_can_import_a_simple_xlsx_file_from_uploaded_file\":0.005,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::test_can_import_a_simple_xlsx_file_from_real_path\":0.005,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::test_import_will_throw_error_when_no_reader_type_could_be_detected_when_no_extension\":0.001,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::test_import_will_throw_error_when_no_reader_type_could_be_detected_with_unknown_extension\":0.035,\"Maatwebsite\\\\Excel\\\\Tests\\\\ExcelTest::test_can_import_without_extension_with_explicit_reader_type\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\HeadingRowImportTest::test_can_import_only_heading_row_with_custom_heading_row_formatter\":0.003,\"Maatwebsite\\\\Excel\\\\Tests\\\\HeadingRowImportTest::test_can_import_only_heading_row_with_custom_heading_row_formatter_with_key\":0.003,\"Maatwebsite\\\\Excel\\\\Tests\\\\HeadingRowImportTest::test_can_import_only_heading_row_with_custom_row_number\":0.005,\"Maatwebsite\\\\Excel\\\\Tests\\\\HeadingRowImportTest::test_can_import_only_heading_row_for_multiple_sheets\":0.003,\"Maatwebsite\\\\Excel\\\\Tests\\\\HeadingRowImportTest::test_can_import_only_heading_row_for_multiple_sheets_with_key\":0.005,\"Maatwebsite\\\\Excel\\\\Tests\\\\HeadingRowImportTest::test_can_import_only_heading_row_for_multiple_sheets_with_custom_row_number\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\HeadingRowImportTest::test_can_import_heading_row_with_custom_formatter_defined_in_config\":0.004,\"Maatwebsite\\\\Excel\\\\Tests\\\\InteractsWithQueueTest::test_read_chunk_job_can_interact_with_queue\":0.001,\"Maatwebsite\\\\Excel\\\\Tests\\\\InteractsWithQueueTest::test_append_data_to_sheet_job_can_interact_with_queue\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\InteractsWithQueueTest::test_append_query_to_sheet_job_can_interact_with_queue\":0.001,\"Maatwebsite\\\\Excel\\\\Tests\\\\InteractsWithQueueTest::test_append_view_to_sheet_job_can_interact_with_queue\":0.001,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\DownloadCollectionTest::test_can_download_a_collection_as_excel\":0.011,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\DownloadCollectionTest::test_can_download_a_collection_with_headers_as_excel\":0.011,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\DownloadCollectionTest::test_can_download_collection_with_headers_with_hidden_eloquent_attributes\":0.011,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\DownloadCollectionTest::test_can_download_collection_with_headers_when_making_attributes_visible\":0.011,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\DownloadCollectionTest::test_can_set_custom_response_headers\":0.008,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\DownloadQueryMacroTest::test_can_download_a_query_as_excel\":0.058,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\DownloadQueryMacroTest::test_can_download_a_collection_with_headers_as_excel\":0.062,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\ImportAsMacroTest::test_can_import_directly_into_a_model_with_mapping\":0.032,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\ImportMacroTest::test_can_import_directly_into_a_model\":0.035,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\StoreCollectionTest::test_can_store_a_collection_as_excel\":0.012,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\StoreCollectionTest::test_can_store_a_collection_as_excel_on_non_default_disk\":0.01,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\StoreCollectionTest::test_can_store_a_collection_with_headings_as_excel\":0.01,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\StoreCollectionTest::test_can_store_a_model_collection_with_headings_as_excel\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\StoreQueryMacroTest::test_can_download_a_query_as_excel\":0.061,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\StoreQueryMacroTest::test_can_download_a_query_as_excel_on_different_disk\":0.059,\"Maatwebsite\\\\Excel\\\\Tests\\\\Mixins\\\\StoreQueryMacroTest::test_can_store_a_query_with_headers_as_excel\":0.065,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedExportTest::test_can_queue_an_export\":0.365,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedExportTest::test_can_queue_an_export_and_store_on_different_disk\":0.349,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedExportTest::test_can_queue_export_with_remote_temp_disk\":0.444,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedExportTest::test_can_queue_export_with_remote_temp_disk_and_prefix\":0.335,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedExportTest::test_can_implicitly_queue_an_export\":0.332,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedExportTest::test_can_queue_export_with_mapping_on_eloquent_models\":0.029,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedExportTest::test_can_catch_failures\":0.01,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedExportTest::test_can_catch_failures_on_queue_export_job\":0.003,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedExportTest::test_can_set_locale_on_queue_export_job\":0.03,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedExportTest::test_can_queue_export_not_flushing_the_cache\":0.385,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedImportTest::test_cannot_queue_import_that_does_not_implement_should_queue\":0.046,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedImportTest::test_can_queue_an_import\":2.07,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedImportTest::test_can_queue_an_import_with_batch_cache_and_file_store\":3.877,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedImportTest::test_can_queue_import_with_remote_temp_disk\":2.219,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedImportTest::test_can_keep_extension_for_temp_file_on_remote_disk\":2.262,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedImportTest::test_can_queue_import_with_remote_temp_disk_and_prefix\":2.062,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedImportTest::test_can_automatically_delete_temp_file_on_failure_when_using_remote_disk\":0.108,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedImportTest::test_cannot_automatically_delete_temp_file_on_failure_when_using_local_disk\":0.106,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedImportTest::test_can_force_remote_download_and_deletion_for_each_chunk_on_queue\":2.176,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedImportTest::test_can_define_middleware_method_on_queued_import\":0.067,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedImportTest::test_can_define_retry_until_method_on_queued_import\":0.064,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedImportTest::test_can_define_max_exceptions_property_on_queued_import\":0.106,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedQueryExportTest::test_can_queue_an_export\":0.205,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedQueryExportTest::test_can_queue_an_export_with_batch_cache_and_file_store\":3.691,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedQueryExportTest::test_can_queue_an_export_with_mapping\":0.051,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedQueryExportTest::test_can_queue_scout_export\":0.372,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedViewExportTest::test_can_queue_an_export\":0.138,\"Maatwebsite\\\\Excel\\\\Tests\\\\QueuedViewExportTest::test_can_export_multiple_sheets_from_view\":0.266,\"Maatwebsite\\\\Excel\\\\Tests\\\\TemporaryFileTest::test_can_use_default_rights\":0.002,\"Maatwebsite\\\\Excel\\\\Tests\\\\TemporaryFileTest::test_can_use_dir_rights\":0.001,\"Maatwebsite\\\\Excel\\\\Tests\\\\TemporaryFileTest::test_can_use_file_rights\":0.001,\"Maatwebsite\\\\Excel\\\\Tests\\\\Concerns\\\\ImportableTest::test_cannot_import_a_non_existing_xlsx_file\":0.001,\"Maatwebsite\\\\Excel\\\\Tests\\\\Validators\\\\RowValidatorTest::test_format_rule_with_array_input\":0.025,\"Maatwebsite\\\\Excel\\\\Tests\\\\Validators\\\\RowValidatorTest::test_format_rule_with_object_input\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\Validators\\\\RowValidatorTest::test_format_rule_with_callable_input\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\Validators\\\\RowValidatorTest::test_format_rule_with_string_input_matching_pattern\":0.006,\"Maatwebsite\\\\Excel\\\\Tests\\\\Validators\\\\RowValidatorTest::test_format_rule_with_string_input_not_matching_pattern\":0,\"Maatwebsite\\\\Excel\\\\Tests\\\\Validators\\\\RowValidatorTest::test_format_rule_with_required_without_all\":0.006,\"Maatwebsite\\\\Excel\\\\Tests\\\\Validators\\\\RowValidatorTest::test_format_rule_with_required_without\":0}}"
  },
  {
    "path": ".styleci.yml",
    "content": "preset: laravel\n\nrisky: false\n\nenabled:\n  - align_double_arrow\n  - align_equals\n  - concat_with_spaces\n  - ordered_class_elements\n\ndisabled:\n  - concat_without_spaces\n  - not_operator_with_successor_space\n  - unalign_equals\n\nfinder:\n  not-name:\n    - \"*.md\"\n  not-path:\n    - \".github\""
  },
  {
    "path": "CHANGELOG.md",
    "content": "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nPlease view https://github.com/SpartnerNL/Laravel-Excel/releases for the most recent changelog\n\n## [3.1.47] - 2023-02-16\n\n- Support Laravel 10\n\n### Fixed\n\n- Fix Bug Multiple drawings change the behavior of the startCell (#3865).\n- Allow configuring read data only in chunks as well.\n\n## [3.1.46] - 2023-01-27\n\n- Support Laravel 10\n\n## [3.1.45] - 2023-01-02\n\n### Added\n- Add support for ignoring PHP auto_detect_line_endings INI directive\n\n### Fixed\n- Fix the PSR simple cache dependency mess to maintain backwards compatibility and support 3.0 of the interface.\n\n## [3.1.44] - 2022-10-14\n\n### Fixed\n\n- Fix output of `WithFormatData` in combination with `SkipsEmptyRows` (#3760)\n\n### Changed\n- Cast empty headings to indexed integer (#3646)\n- Adds `isEmptyWhen` to customize is row empty logic. (#3645)\n\n### Fixed\n\n- Fix temporary local files not being cleaned up when setting force_resync_remote config to true (#3623)\n- Fix testing for multiple stored files by regex matching (#3631).\n- Allow `required_unless` rule (#3660)\n\n## [3.1.40] - 2022-05-02\n\n- Fix testing for multiple stored files by regex matching (#3631).\n\n### Changed\n\n- Adds `WithDefaultStyles` concern to allow configuring the workbook default styles.\n- Adds `WithBackgroundColor` concern to allow configuring the workbook default background color.\n- Expose the ability to set custom response headers when exporting collections via Exportable\n\n## [3.1.39] - 2022-04-23\n\n### Fixed\n\n- Fix PHP8.1 return type for Failure class (#3588)\n\n## [3.1.38] - 2022-03-24\n\n### Changed\n\n- Adds concern `WithGroupedHeadingRow` to allow imported sheets to group the values of columns with the same header in an array\n\n### Fixed\n\n- Fix for `prepareForValidation` callback not being called when using `SkipsEmptyRows`\n\n## [3.1.37] - 2022-02-28\n\n### Fixed\n\n- Add `@mixin` docblock to all macroable classes to allow for IDE autocompletion of delegate classes\n- Fix issue with `Excel::toArray` not allowing nullable reader types for uploaded files\n\n### Changed\n\n- Change default Csv Import to auto-detect the delimiter when not explicitly defined\n\n## [3.1.36] - 2022-02-03\n\n### Fixed\n\n- Fix return type of `FromQuery::query()`\n\n### Changed\n\n- Support Laravel 9\n- Added a config setting to specify DB connection\n- Added a config setting to specify CSV output encoding\n- Added an ability to specify CSV output encoding through csvSettings\n\n## [3.1.35] - 2022-01-04\n\n### Fixed\n\n- Removed cache flush for cell caching as this is already handled by PhpSpreadsheet\n- Fix `SkipsEmptyRows` support with the `WithColumnLimit` concern\n- Added range support to FormatColumn\n\n## [3.1.34] - 2021-12-2\n\n### Changed\n\n- Change default local_path configuration\n- Fix queueImport function to be able to assert chained jobs\n- Skipped failure no longer persists in `ToCollection` and `ToArray`.\n- Fix missing InteractsWithQueue trait in AppendToSheet jobs\n- Add return types to `Row`'s `ArrayAccess` implementation\n\n## [3.1.33] - 2021-08-12\n\n### Fixed\n\n- Make TransactionManager a singleton (#3270)\n- Fix Exportable disk options (#3296)\n- Delete temporary file after exception in import class (#3312)\n\n## [3.1.32] - 2021-07-08\n\n### Added\n\n- Add assertExportedInRaw assertion (#3255)\n\n### Fixed\n\n- Make commands detect model directory now (#3213)\n\n## [3.1.31] - 2021-06-02\n\n### Added\n\n- Custom heading row formatter can use column index (#3166)\n- Added WithFormatData concern (#3154)\n\n### Fixed\n\n- Create failures of rows than didn't exist but where requested in row\n  validation\n- Fix Bug Formulas are not calculated when import implements\n  WithCalculatedFormulas with SkipsEmptyRows #3127\n- PhpSpreadsheet 1.18 support\n\n## [3.1.30] - 2021-04-06\n\n### Added\n\n- Octane compatibility\n\n## [3.1.29] - 2021-03-16\n\n### Fixed\n\n- Fix AfterImport Event not being called (#3085)\n\n## [3.1.28] - 2021-03-10\n\n### Added\n\n- Added WithUpsertColumns concern (#3046)\n- Added ShouldQueueWithoutChain concern (#3072)\n\n### Fixed\n\n- Limit Phpspreadsheet version to 1.16 until bugfix release\n- Fixed issue with not autosizing columns (#3055)\n- Fix selecting worksheets by name with chunk reading (#3052)\n\n## [3.1.27] - 2021-02-22\n\n### Added\n\n- Added SkipsEmptyRows concern\n- Added HasReferencesToOtherSheets concern to allow import of calculated\n\n### Changed\n\n- Bump minimum PhpSpreadsheet version\n- Progressbar NullOutput as fallback\n\n## [3.1.26] - 2020-11-13\n\n### Added\n\n- PHP 8 support\n\n## [3.1.25] - 2020-11-13\n\n### Added\n\n- Added an ability to prepare rows before appending rows to sheet. Just add\n  `prepareRows` method for your export class if needed.\n- Added an ability to catch exceptions from `QueueExport` job. Just add `failed`\n  method for your export class if needed.\n- Added an ability to set locale for queued export. Just implement\n  `Illuminate\\Contracts\\Translation\\HasLocalePreference` for your export.\n- Added `JsonSerializable` support in `Maatwebsite\\Excel\\Validators\\Failure`.\n- Added `$maxExceptions` support in `Maatwebsite\\Excel\\Jobs\\ReadChunk.php`.\n- Added support to upsert models by implementing the `WithUpserts` concern.\n\n## [3.1.24] - 2020-10-28\n\n### Added\n\n- Added support for `prepareForValidation` on `WithValidation` concern\n- Added support for `withValidator` on `WithValidation` concern\n- Added `ArrayAccess` to `Row`\n\n### Fixed\n\n- Corrected SkipsErrors doc block\n\n## [3.1.23] - 2020-09-29\n\n### Added\n\n- Added `ignore_empty` setting to `config/excel.php`\n- Added `strict_null_comparison` setting to `config/excel.php`\n\n## [3.1.22] - 2020-09-08\n\n- Laravel 8 support\n- Lumen improvements\n\n## [3.1.21] - 2020-08-06\n\n### Added\n\n- Added WithProperties concern\n- Added default spreadsheet properties config\n- Added WithColumnWidths concern\n- Added WithStyles concern.\n- Config setting to configure cell caching\n\n### Changed\n\n- Sheet titles longer than 31 chars get trimmed.\n- Sheet titles with unsupported chars get cleaned.\n\n### Fixed\n\n- Fixed issue with using ShouldAutosize in combination with FromView column\n  widths.\n\n## [3.1.20] - 2020-07-22\n\n### Added\n\n- Re-sycing remote temporary file\n- Remember row number\n- Remember chunk offset\n- WithColumnLimit concern\n- WithReadFilter concern\n- Publishing the stubs\n\n### Changed\n\n- Interacting with queued jobs\n- Retry until and middleware on queued imports\n- Using WithValidation with FromCollection & FromArray\n- Read filters for WithLimit and HeadingRowImport\n- Bump of minimum version PhpSpreadsheet\n\n### Fixed\n\n- Fixed test helper docblocks on the Excel facade.\n- Fix for importing with a start row beyond the highest row.\n- Fixed `BeforeSheet` and `AfterSheet` events receiving exportable instance\n  instead of importable when calling on an Import.\n- Fix for value binders not working in queued exports.\n- Fix when using WithLimit concern when having less rows than the limit.\n- Fix AfterImport job being fired twice if not using queueing.\n- Raw() method now also available on Exportable.\n- Fix for breaking changes in PhpSpreadsheet with empty enclosures.\n\n[Unreleased]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.47...HEAD\n[3.1.47]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.46...3.1.47\n[3.1.46]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.45...3.1.46\n[3.1.45]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.44...3.1.45\n[3.1.44]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.43...3.1.44\n[3.1.43]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.42...3.1.43\n[3.1.42]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.41...3.1.42\n[3.1.41]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.40...3.1.41\n[3.1.40]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.39...3.1.40\n[3.1.39]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.38...3.1.39\n[3.1.38]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.37...3.1.38\n[3.1.37]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.36...3.1.37\n[3.1.36]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.35...3.1.36\n[3.1.35]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.34...3.1.35\n[3.1.34]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.33...3.1.34\n[3.1.33]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.32...3.1.33\n[3.1.32]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.31...3.1.32\n[3.1.31]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.30...3.1.31\n[3.1.30]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.29...3.1.30\n[3.1.29]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.28...3.1.29\n[3.1.28]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.27...3.1.28\n[3.1.27]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.26...3.1.27\n[3.1.26]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.25...3.1.26\n[3.1.25]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.24...3.1.25\n[3.1.24]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.23...3.1.24\n[3.1.23]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.22...3.1.23\n[3.1.22]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.21...3.1.22\n[3.1.21]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.20...3.1.21\n[3.1.20]: https://github.com/Maatwebsite/Laravel-Excel/compare/3.1.19...3.1.20\n\n_Older release notes can be found in Github releases._\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.\n\n## Our Standards\n\nExamples of behavior that contributes to creating a positive environment include:\n\n* Using welcoming and inclusive language\n* Being respectful of differing viewpoints and experiences\n* Gracefully accepting constructive criticism\n* Focusing on what is best for the community\n* Showing empathy towards other community members\n\nExamples of unacceptable behavior by participants include:\n\n* The use of sexualized language or imagery and unwelcome sexual attention or advances\n* Trolling, insulting/derogatory comments, and personal or political attacks\n* Public or private harassment\n* Publishing others' private information, such as a physical or electronic address, without explicit permission\n* Other conduct which could reasonably be considered inappropriate in a professional setting\n\n## Our Responsibilities\n\nProject maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.\n\nProject maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.\n\n## Scope\n\nThis Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at patrick@spartner.nl. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.\n\nProject maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]\n\n[homepage]: http://contributor-covenant.org\n[version]: http://contributor-covenant.org/version/1/4/\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing\n\nFind the contributing guide at: https://docs.laravel-excel.com/3.1/getting-started/contributing.html\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) Spartner\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "<br />\n<br />\n<p align=\"center\">\n  <!-- XMAS: https://user-images.githubusercontent.com/7728097/146406114-a5f5e13a-e2ee-47a2-9bf9-ad43cdbdf200.png-->\n<img width=\"589\" src=\"https://user-images.githubusercontent.com/7728097/143205384-af3c73a8-0253-45f3-b5ac-28a335dddb87.png\" alt=\"Laravel Excel logo\">\n</p>\n<br />\n\n\n<h3 align=\"center\">Supercharged Excel exports and imports</h3>\n\n  <p align=\"center\">\n  A simple, but elegant <a href=\"https://laravel.com\" target=\"_blank\">Laravel<a/> wrapper around <a href=\"https://phpspreadsheet.readthedocs.io/\" target=\"_blank\">PhpSpreadsheet</a>\nexports and imports.\n</p>\n\n<h4 align=\"center\">\n  <a href=\"https://docs.laravel-excel.com/3.1/exports/\">Quickstart</a>\n  <span> · </span>\n  <a href=\"https://docs.laravel-excel.com/3.1/getting-started/\">Documentation</a>\n  <span> · </span>\n  <a href=\"https://course.laravel-excel.com\">Video Course</a>\n  <span> · </span>\n  <a href=\"https://github.com/SpartnerNL/Laravel-Nova-Excel\">Nova</a>\n  <span> · </span>\n  <a href=\"https://medium.com/maatwebsite/laravel-excel/home\">Blog</a>\n  <span> · </span>\n  <a href=\"https://docs.laravel-excel.com/3.1/getting-started/contributing.html\">Contributing</a>\n  <span> · </span>\n  <a href=\"https://docs.laravel-excel.com/3.1/getting-started/support.html\">Support</a>\n</h4>\n\n<p align=\"center\">\n  <a href=\"https://github.com/SpartnerNL/Laravel-Excel/actions\">\n    <img src=\"https://github.com/SpartnerNL/Laravel-Excel/actions/workflows/run-tests.yml/badge.svg\" alt=\"Github Actions\">\n  </a>\n\n  <a href=\"https://styleci.io/repos/14259390\">\n    <img src=\"https://styleci.io/repos/14259390/shield?branch=3.1\" alt=\"StyleCI\">\n  </a>\n\n   <a href=\"https://packagist.org/packages/maatwebsite/excel\">\n      <img src=\"https://poser.pugx.org/maatwebsite/excel/v/stable.png\" alt=\"Latest Stable Version\">\n  </a>\n\n  <a href=\"https://packagist.org/packages/maatwebsite/excel\">\n      <img src=\"https://poser.pugx.org/maatwebsite/excel/downloads.png\" alt=\"Total Downloads\">\n  </a>\n\n  <a href=\"https://github.com/SpartnerNL/Laravel-Excel/blob/3.1/LICENSE\">\n    <img src=\"https://poser.pugx.org/maatwebsite/excel/license.png\" alt=\"License\">\n  </a>\n</p>\n\n## ✨ Features\n\n- **Easily export collections to Excel.** Supercharge your Laravel collections and export them directly to an Excel or CSV document. Exporting has never been so easy.\n\n- **Supercharged exports.** Export queries with automatic chunking for better performance. You provide us the query, we handle the performance. Exporting even larger datasets? No worries, Laravel Excel has your back. You can queue your exports so all of this happens in the background.\n\n- **Supercharged imports.** Import workbooks and worksheets to Eloquent models with chunk reading and batch inserts! Have large files? You can queue every chunk of a file! Your entire import will happen in the background.\n\n- **Export Blade views.** Want to have a custom layout in your spreadsheet? Use a HTML table in a Blade view and export that to Excel.\n\n![banner](https://user-images.githubusercontent.com/7728097/57463977-2263fc80-727c-11e9-833d-669d816fb7fb.jpg)\n<br>\n\n## 🎓 Learning Laravel Excel\n\nYou can find the full documentation of Laravel Excel [on the website](https://docs.laravel-excel.com).\n\nWe welcome suggestions for improving our docs. The documentation repository can be found at [https://github.com/SpartnerNL/laravel-excel-docs](https://github.com/SpartnerNL/laravel-excel-docs).\n\nSome articles and tutorials can be found on our blog: https://medium.com/maatwebsite/laravel-excel/home\n\n## :mailbox_with_mail: License & Postcardware\n\n![1_5nblgs68uarg0wxxejozdq](https://user-images.githubusercontent.com/7728097/53638144-9e5f1a00-3c25-11e9-9f4a-fc71c9d94562.jpg)\n\nLaravel Excel is created with love and care by Spartner (formerly known as Maatwebsite) to give back to the Laravel community. It is completely free (MIT license) to use, however the package is licensed as Postcardware. This means that if it makes it to your production environment, we would very much appreciate receiving a postcard from your hometown.\n\n**Spartner**\nMarkt 2\n6231 LS Meerssen\nThe Netherlands.\n\nMore about the license can be found at: [https://docs.laravel-excel.com/3.1/getting-started/license.html](https://docs.laravel-excel.com/3.1/getting-started/license.html)\n\n## Created by Spartner (formerly Maatwebsite)\n\nWe are a strategic development partner, creating web-based custom built software from Laravel. In need of a digital solution for your challenge? Give us a call.\n\nhttps://spartner.software\ninfo@spartner.nl\n+31 (0) 10 - 7449312\n\n## :wrench: Supported Versions\n\nVersions will be supported for a limited amount of time.\n\n| Version | Laravel Version | Php Version | Support |\n|---- |----|----|----|\n| 2.1 | <=5.6 | <=7.0 | Unsupported since 15-5-2018 |\n| 3.0 | ^5.5 |  ^7.0 | Unsupported since 31-12-2018 |\n| 3.1 | >=5.8 \\| <=12.x |  ^7.2 \\| ^8.0 | New features |\n"
  },
  {
    "path": "SECURITY.md",
    "content": "# Security Policy\n\n**PLEASE DON'T DISCLOSE SECURITY-RELATED ISSUES PUBLICLY, [SEE BELOW](#reporting-a-vulnerability).**\n\n## Supported Versions\n\nVersion | Security Fixes Until\n--- | ---\n3.1\t| -\n3.0\t| 31-12-2018\n2.1\t| 15-5-2018\n\n## Reporting a Vulnerability\n\nIf you discover a security vulnerability within Laravel Excel, please send an email to Patrick Brouwers at patrick@spartner.nl. All security vulnerabilities will be promptly addressed.\n"
  },
  {
    "path": "composer.json",
    "content": "{\n  \"name\": \"maatwebsite/excel\",\n  \"description\": \"Supercharged Excel exports and imports in Laravel\",\n  \"license\": \"MIT\",\n  \"keywords\": [\n    \"laravel\",\n    \"php\",\n    \"phpspreadsheet\",\n    \"phpexcel\",\n    \"excel\",\n    \"csv\",\n    \"export\",\n    \"import\",\n    \"batch\"\n  ],\n  \"authors\": [\n    {\n      \"name\": \"Patrick Brouwers\",\n      \"email\": \"patrick@spartner.nl\"\n    }\n  ],\n  \"require\": {\n    \"ext-json\": \"*\",\n    \"php\": \"^7.0||^8.0\",\n    \"phpoffice/phpspreadsheet\": \"^1.30.0\",\n    \"illuminate/support\": \"5.8.*||^6.0||^7.0||^8.0||^9.0||^10.0||^11.0||^12.0||^13.0\",\n    \"psr/simple-cache\": \"^1.0||^2.0||^3.0\",\n    \"composer/semver\": \"^3.3\"\n  },\n  \"require-dev\": {\n    \"orchestra/testbench\": \"^6.0||^7.0||^8.0||^9.0||^10.0||^11.0\",\n    \"predis/predis\": \"^1.1\",\n    \"laravel/scout\": \"^7.0||^8.0||^9.0||^10.0||^11.0\"\n  },\n  \"autoload\": {\n    \"psr-4\": {\n      \"Maatwebsite\\\\Excel\\\\\": \"src/\"\n    }\n  },\n  \"autoload-dev\": {\n    \"psr-4\": {\n      \"Maatwebsite\\\\Excel\\\\Tests\\\\\": \"tests/\"\n    }\n  },\n  \"extra\": {\n    \"laravel\": {\n      \"providers\": [\n        \"Maatwebsite\\\\Excel\\\\ExcelServiceProvider\"\n      ],\n      \"aliases\": {\n        \"Excel\": \"Maatwebsite\\\\Excel\\\\Facades\\\\Excel\"\n      }\n    }\n  },\n  \"minimum-stability\": \"dev\",\n  \"prefer-stable\": true\n}\n"
  },
  {
    "path": "config/excel.php",
    "content": "<?php\n\nuse Maatwebsite\\Excel\\Excel;\nuse PhpOffice\\PhpSpreadsheet\\Reader\\Csv;\n\nreturn [\n    'exports' => [\n\n        /*\n        |--------------------------------------------------------------------------\n        | Chunk size\n        |--------------------------------------------------------------------------\n        |\n        | When using FromQuery, the query is automatically chunked.\n        | Here you can specify how big the chunk should be.\n        |\n        */\n        'chunk_size'             => 1000,\n\n        /*\n        |--------------------------------------------------------------------------\n        | Pre-calculate formulas during export\n        |--------------------------------------------------------------------------\n        */\n        'pre_calculate_formulas' => false,\n\n        /*\n        |--------------------------------------------------------------------------\n        | Enable strict null comparison\n        |--------------------------------------------------------------------------\n        |\n        | When enabling strict null comparison empty cells ('') will\n        | be added to the sheet.\n        */\n        'strict_null_comparison' => false,\n\n        /*\n        |--------------------------------------------------------------------------\n        | CSV Settings\n        |--------------------------------------------------------------------------\n        |\n        | Configure e.g. delimiter, enclosure and line ending for CSV exports.\n        |\n        */\n        'csv'                    => [\n            'delimiter'              => ',',\n            'enclosure'              => '\"',\n            'line_ending'            => PHP_EOL,\n            'use_bom'                => false,\n            'include_separator_line' => false,\n            'excel_compatibility'    => false,\n            'output_encoding'        => '',\n            'test_auto_detect'       => true,\n        ],\n\n        /*\n        |--------------------------------------------------------------------------\n        | Worksheet properties\n        |--------------------------------------------------------------------------\n        |\n        | Configure e.g. default title, creator, subject,...\n        |\n        */\n        'properties'             => [\n            'creator'        => '',\n            'lastModifiedBy' => '',\n            'title'          => '',\n            'description'    => '',\n            'subject'        => '',\n            'keywords'       => '',\n            'category'       => '',\n            'manager'        => '',\n            'company'        => '',\n        ],\n    ],\n\n    'imports'            => [\n\n        /*\n        |--------------------------------------------------------------------------\n        | Read Only\n        |--------------------------------------------------------------------------\n        |\n        | When dealing with imports, you might only be interested in the\n        | data that the sheet exists. By default we ignore all styles,\n        | however if you want to do some logic based on style data\n        | you can enable it by setting read_only to false.\n        |\n        */\n        'read_only'    => true,\n\n        /*\n        |--------------------------------------------------------------------------\n        | Ignore Empty\n        |--------------------------------------------------------------------------\n        |\n        | When dealing with imports, you might be interested in ignoring\n        | rows that have null values or empty strings. By default rows\n        | containing empty strings or empty values are not ignored but can be\n        | ignored by enabling the setting ignore_empty to true.\n        |\n        */\n        'ignore_empty' => false,\n\n        /*\n        |--------------------------------------------------------------------------\n        | Heading Row Formatter\n        |--------------------------------------------------------------------------\n        |\n        | Configure the heading row formatter.\n        | Available options: none|slug|custom\n        |\n        */\n        'heading_row'  => [\n            'formatter' => 'slug',\n        ],\n\n        /*\n        |--------------------------------------------------------------------------\n        | CSV Settings\n        |--------------------------------------------------------------------------\n        |\n        | Configure e.g. delimiter, enclosure and line ending for CSV imports.\n        |\n        */\n        'csv'          => [\n            'delimiter'        => null,\n            'enclosure'        => '\"',\n            'escape_character' => '\\\\',\n            'contiguous'       => false,\n            'input_encoding'   => Csv::GUESS_ENCODING,\n        ],\n\n        /*\n        |--------------------------------------------------------------------------\n        | Worksheet properties\n        |--------------------------------------------------------------------------\n        |\n        | Configure e.g. default title, creator, subject,...\n        |\n        */\n        'properties'   => [\n            'creator'        => '',\n            'lastModifiedBy' => '',\n            'title'          => '',\n            'description'    => '',\n            'subject'        => '',\n            'keywords'       => '',\n            'category'       => '',\n            'manager'        => '',\n            'company'        => '',\n        ],\n\n        /*\n       |--------------------------------------------------------------------------\n       | Cell Middleware\n       |--------------------------------------------------------------------------\n       |\n       | Configure middleware that is executed on getting a cell value\n       |\n       */\n        'cells'        => [\n            'middleware' => [\n                //\\Maatwebsite\\Excel\\Middleware\\TrimCellValue::class,\n                //\\Maatwebsite\\Excel\\Middleware\\ConvertEmptyCellValuesToNull::class,\n            ],\n        ],\n\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Extension detector\n    |--------------------------------------------------------------------------\n    |\n    | Configure here which writer/reader type should be used when the package\n    | needs to guess the correct type based on the extension alone.\n    |\n    */\n    'extension_detector' => [\n        'xlsx'     => Excel::XLSX,\n        'xlsm'     => Excel::XLSX,\n        'xltx'     => Excel::XLSX,\n        'xltm'     => Excel::XLSX,\n        'xls'      => Excel::XLS,\n        'xlt'      => Excel::XLS,\n        'ods'      => Excel::ODS,\n        'ots'      => Excel::ODS,\n        'slk'      => Excel::SLK,\n        'xml'      => Excel::XML,\n        'gnumeric' => Excel::GNUMERIC,\n        'htm'      => Excel::HTML,\n        'html'     => Excel::HTML,\n        'csv'      => Excel::CSV,\n        'tsv'      => Excel::TSV,\n\n        /*\n        |--------------------------------------------------------------------------\n        | PDF Extension\n        |--------------------------------------------------------------------------\n        |\n        | Configure here which Pdf driver should be used by default.\n        | Available options: Excel::MPDF | Excel::TCPDF | Excel::DOMPDF\n        |\n        */\n        'pdf'      => Excel::DOMPDF,\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Value Binder\n    |--------------------------------------------------------------------------\n    |\n    | PhpSpreadsheet offers a way to hook into the process of a value being\n    | written to a cell. In there some assumptions are made on how the\n    | value should be formatted. If you want to change those defaults,\n    | you can implement your own default value binder.\n    |\n    | Possible value binders:\n    |\n    | [x] Maatwebsite\\Excel\\DefaultValueBinder::class\n    | [x] PhpOffice\\PhpSpreadsheet\\Cell\\StringValueBinder::class\n    | [x] PhpOffice\\PhpSpreadsheet\\Cell\\AdvancedValueBinder::class\n    |\n    */\n    'value_binder'       => [\n        'default' => Maatwebsite\\Excel\\DefaultValueBinder::class,\n    ],\n\n    'cache'        => [\n        /*\n        |--------------------------------------------------------------------------\n        | Default cell caching driver\n        |--------------------------------------------------------------------------\n        |\n        | By default PhpSpreadsheet keeps all cell values in memory, however when\n        | dealing with large files, this might result into memory issues. If you\n        | want to mitigate that, you can configure a cell caching driver here.\n        | When using the illuminate driver, it will store each value in the\n        | cache store. This can slow down the process, because it needs to\n        | store each value. You can use the \"batch\" store if you want to\n        | only persist to the store when the memory limit is reached.\n        |\n        | Drivers: memory|illuminate|batch\n        |\n        */\n        'driver'      => 'memory',\n\n        /*\n        |--------------------------------------------------------------------------\n        | Batch memory caching\n        |--------------------------------------------------------------------------\n        |\n        | When dealing with the \"batch\" caching driver, it will only\n        | persist to the store when the memory limit is reached.\n        | Here you can tweak the memory limit to your liking.\n        |\n        */\n        'batch'       => [\n            'memory_limit' => 60000,\n        ],\n\n        /*\n        |--------------------------------------------------------------------------\n        | Illuminate cache\n        |--------------------------------------------------------------------------\n        |\n        | When using the \"illuminate\" caching driver, it will automatically use\n        | your default cache store. However if you prefer to have the cell\n        | cache on a separate store, you can configure the store name here.\n        | You can use any store defined in your cache config. When leaving\n        | at \"null\" it will use the default store.\n        |\n        */\n        'illuminate'  => [\n            'store' => null,\n        ],\n\n        /*\n        |--------------------------------------------------------------------------\n        | Cache Time-to-live (TTL)\n        |--------------------------------------------------------------------------\n        |\n        | The TTL of items written to cache. If you want to keep the items cached\n        | indefinitely, set this to null.  Otherwise, set a number of seconds,\n        | a \\DateInterval, or a callable.\n        |\n        | Allowable types: callable|\\DateInterval|int|null\n        |\n         */\n        'default_ttl' => 10800,\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Transaction Handler\n    |--------------------------------------------------------------------------\n    |\n    | By default the import is wrapped in a transaction. This is useful\n    | for when an import may fail and you want to retry it. With the\n    | transactions, the previous import gets rolled-back.\n    |\n    | You can disable the transaction handler by setting this to null.\n    | Or you can choose a custom made transaction handler here.\n    |\n    | Supported handlers: null|db\n    |\n    */\n    'transactions' => [\n        'handler' => 'db',\n        'db'      => [\n            'connection' => null,\n        ],\n    ],\n\n    'temporary_files' => [\n\n        /*\n        |--------------------------------------------------------------------------\n        | Local Temporary Path\n        |--------------------------------------------------------------------------\n        |\n        | When exporting and importing files, we use a temporary file, before\n        | storing reading or downloading. Here you can customize that path.\n        | permissions is an array with the permission flags for the directory (dir)\n        | and the create file (file).\n        |\n        */\n        'local_path'          => storage_path('framework/cache/laravel-excel'),\n\n        /*\n        |--------------------------------------------------------------------------\n        | Local Temporary Path Permissions\n        |--------------------------------------------------------------------------\n        |\n        | Permissions is an array with the permission flags for the directory (dir)\n        | and the create file (file).\n        | If omitted the default permissions of the filesystem will be used.\n        |\n        */\n        'local_permissions'   => [\n            // 'dir'  => 0755,\n            // 'file' => 0644,\n        ],\n\n        /*\n        |--------------------------------------------------------------------------\n        | Remote Temporary Disk\n        |--------------------------------------------------------------------------\n        |\n        | When dealing with a multi server setup with queues in which you\n        | cannot rely on having a shared local temporary path, you might\n        | want to store the temporary file on a shared disk. During the\n        | queue executing, we'll retrieve the temporary file from that\n        | location instead. When left to null, it will always use\n        | the local path. This setting only has effect when using\n        | in conjunction with queued imports and exports.\n        |\n        */\n        'remote_disk'         => null,\n        'remote_prefix'       => null,\n\n        /*\n        |--------------------------------------------------------------------------\n        | Force Resync\n        |--------------------------------------------------------------------------\n        |\n        | When dealing with a multi server setup as above, it's possible\n        | for the clean up that occurs after entire queue has been run to only\n        | cleanup the server that the last AfterImportJob runs on. The rest of the server\n        | would still have the local temporary file stored on it. In this case your\n        | local storage limits can be exceeded and future imports won't be processed.\n        | To mitigate this you can set this config value to be true, so that after every\n        | queued chunk is processed the local temporary file is deleted on the server that\n        | processed it.\n        |\n        */\n        'force_resync_remote' => null,\n    ],\n];\n"
  },
  {
    "path": "phpunit.xml.dist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<phpunit xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" backupGlobals=\"false\" bootstrap=\"vendor/autoload.php\" colors=\"true\" processIsolation=\"false\" stopOnFailure=\"false\" xsi:noNamespaceSchemaLocation=\"https://schema.phpunit.de/10.3/phpunit.xsd\" cacheDirectory=\".phpunit.cache\" backupStaticProperties=\"false\">\n  <coverage/>\n  <php>\n    <env name=\"APP_KEY\" value=\"base64:6igsHe3RYC88h3Wje3VzSNqPwUr7Z5ru+NZw/9qwY5M=\"/>\n    <env name=\"DB_HOST\" value=\"127.0.0.1\"/>\n    <env name=\"DB_PORT\" value=\"3306\"/>\n    <env name=\"DB_DATABASE\" value=\"laravel_excel\"/>\n    <env name=\"DB_USERNAME\" value=\"root\"/>\n    <env name=\"DB_PASSWORD\" value=\"\"/>\n  </php>\n  <testsuites>\n    <testsuite name=\"Package Test Suite\">\n      <directory suffix=\"Test.php\">./tests/</directory>\n    </testsuite>\n  </testsuites>\n  <source>\n    <include>\n      <directory suffix=\".php\">./src</directory>\n    </include>\n  </source>\n</phpunit>\n"
  },
  {
    "path": "src/Cache/BatchCache.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Cache;\n\nuse Illuminate\\Support\\Facades\\Cache;\nuse Psr\\SimpleCache\\CacheInterface;\n\nclass BatchCache implements CacheInterface\n{\n    /**\n     * @var CacheInterface\n     */\n    protected $cache;\n\n    /**\n     * @var MemoryCache\n     */\n    protected $memory;\n\n    /**\n     * @var null|int|\\DateInterval|callable\n     */\n    protected $defaultTTL = null;\n\n    /**\n     * @param  CacheInterface  $cache\n     * @param  MemoryCache  $memory\n     * @param  null|int|\\DateInterval|callable  $defaultTTL\n     */\n    public function __construct(\n        CacheInterface $cache,\n        MemoryCache $memory,\n        null|int|\\DateInterval|callable $defaultTTL = null\n    ) {\n        $this->cache      = $cache;\n        $this->memory     = $memory;\n        $this->defaultTTL = $defaultTTL;\n    }\n\n    public function __sleep()\n    {\n        return ['memory'];\n    }\n\n    public function __wakeup()\n    {\n        $this->cache = Cache::driver(\n            config('excel.cache.illuminate.store')\n        );\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function get(string $key, mixed $default = null): mixed\n    {\n        if ($this->memory->has($key)) {\n            return $this->memory->get($key);\n        }\n\n        return $this->cache->get($key, $default);\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function set(string $key, mixed $value, null|int|\\DateInterval $ttl = null): bool\n    {\n        if (func_num_args() === 2) {\n            $ttl = value($this->defaultTTL);\n        }\n\n        $this->memory->set($key, $value, $ttl);\n\n        if ($this->memory->reachedMemoryLimit()) {\n            return $this->cache->setMultiple($this->memory->flush(), $ttl);\n        }\n\n        return true;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function delete(string $key): bool\n    {\n        if ($this->memory->has($key)) {\n            return $this->memory->delete($key);\n        }\n\n        return $this->cache->delete($key);\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function clear(): bool\n    {\n        $this->memory->clear();\n\n        return $this->cache->clear();\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function getMultiple(iterable $keys, mixed $default = null): iterable\n    {\n        // Check if all keys are still in memory\n        $memory              = $this->memory->getMultiple($keys, $default);\n        $actualItemsInMemory = count(array_filter($memory));\n\n        if ($actualItemsInMemory === count($keys)) {\n            return $memory;\n        }\n\n        // Get all rows from cache if none is hold in memory.\n        if ($actualItemsInMemory === 0) {\n            return $this->cache->getMultiple($keys, $default);\n        }\n\n        // Add missing values from cache.\n        foreach ($this->cache->getMultiple($keys, $default) as $key => $value) {\n            if (null !== $value) {\n                $memory[$key] = $value;\n            }\n        }\n\n        return $memory;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function setMultiple(iterable $values, null|int|\\DateInterval $ttl = null): bool\n    {\n        if (func_num_args() === 1) {\n            $ttl = value($this->defaultTTL);\n        }\n\n        $this->memory->setMultiple($values, $ttl);\n\n        if ($this->memory->reachedMemoryLimit()) {\n            return $this->cache->setMultiple($this->memory->flush(), $ttl);\n        }\n\n        return true;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function deleteMultiple(iterable $keys): bool\n    {\n        $keys = is_array($keys) ? $keys : iterator_to_array($keys);\n\n        $this->memory->deleteMultiple($keys);\n\n        return $this->cache->deleteMultiple($keys);\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function has(string $key): bool\n    {\n        if ($this->memory->has($key)) {\n            return true;\n        }\n\n        return $this->cache->has($key);\n    }\n}\n"
  },
  {
    "path": "src/Cache/BatchCacheDeprecated.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Cache;\n\nuse Illuminate\\Support\\Facades\\Cache;\nuse Psr\\SimpleCache\\CacheInterface;\n\nclass BatchCacheDeprecated implements CacheInterface\n{\n    /**\n     * @var CacheInterface\n     */\n    protected $cache;\n\n    /**\n     * @var MemoryCacheDeprecated\n     */\n    protected $memory;\n\n    /**\n     * @var null|int|\\DateTimeInterface|callable\n     */\n    protected $defaultTTL = null;\n\n    /**\n     * @param  CacheInterface  $cache\n     * @param  MemoryCacheDeprecated  $memory\n     * @param  int|\\DateTimeInterface|callable|null  $defaultTTL\n     */\n    public function __construct(\n        CacheInterface $cache,\n        MemoryCacheDeprecated $memory,\n        $defaultTTL = null\n    ) {\n        $this->cache      = $cache;\n        $this->memory     = $memory;\n        $this->defaultTTL = $defaultTTL;\n    }\n\n    public function __sleep()\n    {\n        return ['memory'];\n    }\n\n    public function __wakeup()\n    {\n        $this->cache = Cache::driver(\n            config('excel.cache.illuminate.store')\n        );\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function get($key, $default = null)\n    {\n        if ($this->memory->has($key)) {\n            return $this->memory->get($key);\n        }\n\n        return $this->cache->get($key, $default);\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function set($key, $value, $ttl = null)\n    {\n        if (func_num_args() === 2) {\n            $ttl = value($this->defaultTTL);\n        }\n\n        $this->memory->set($key, $value, $ttl);\n\n        if ($this->memory->reachedMemoryLimit()) {\n            return $this->cache->setMultiple($this->memory->flush(), $ttl);\n        }\n\n        return true;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function delete($key)\n    {\n        if ($this->memory->has($key)) {\n            return $this->memory->delete($key);\n        }\n\n        return $this->cache->delete($key);\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function clear()\n    {\n        $this->memory->clear();\n\n        return $this->cache->clear();\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function getMultiple($keys, $default = null)\n    {\n        // Check if all keys are still in memory\n        $memory              = $this->memory->getMultiple($keys, $default);\n        $actualItemsInMemory = count(array_filter($memory));\n\n        if ($actualItemsInMemory === count($keys)) {\n            return $memory;\n        }\n\n        // Get all rows from cache if none is hold in memory.\n        if ($actualItemsInMemory === 0) {\n            return $this->cache->getMultiple($keys, $default);\n        }\n\n        // Add missing values from cache.\n        foreach ($this->cache->getMultiple($keys, $default) as $key => $value) {\n            if (null !== $value) {\n                $memory[$key] = $value;\n            }\n        }\n\n        return $memory;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function setMultiple($values, $ttl = null)\n    {\n        if (func_num_args() === 1) {\n            $ttl = value($this->defaultTTL);\n        }\n\n        $this->memory->setMultiple($values, $ttl);\n\n        if ($this->memory->reachedMemoryLimit()) {\n            return $this->cache->setMultiple($this->memory->flush(), $ttl);\n        }\n\n        return true;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function deleteMultiple($keys)\n    {\n        $keys = is_array($keys) ? $keys : iterator_to_array($keys);\n\n        $this->memory->deleteMultiple($keys);\n\n        return $this->cache->deleteMultiple($keys);\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function has($key)\n    {\n        if ($this->memory->has($key)) {\n            return true;\n        }\n\n        return $this->cache->has($key);\n    }\n}\n"
  },
  {
    "path": "src/Cache/CacheManager.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Cache;\n\nuse Composer\\InstalledVersions;\nuse Composer\\Semver\\VersionParser;\nuse Illuminate\\Support\\Facades\\Cache;\nuse Illuminate\\Support\\Manager;\nuse Psr\\SimpleCache\\CacheInterface;\n\nclass CacheManager extends Manager\n{\n    /**\n     * @const string\n     */\n    public const DRIVER_BATCH = 'batch';\n\n    /**\n     * @const string\n     */\n    public const DRIVER_MEMORY = 'memory';\n\n    /**\n     * @const string\n     */\n    public const DRIVER_ILLUMINATE = 'illuminate';\n\n    /**\n     * Get the default driver name.\n     *\n     * @return string\n     */\n    public function getDefaultDriver(): string\n    {\n        return config('excel.cache.driver', 'memory');\n    }\n\n    /**\n     * @return MemoryCache\n     */\n    public function createMemoryDriver(): CacheInterface\n    {\n        if (!InstalledVersions::satisfies(new VersionParser, 'psr/simple-cache', '^3.0')) {\n            return new MemoryCacheDeprecated(\n                config('excel.cache.batch.memory_limit', 60000)\n            );\n        }\n\n        return new MemoryCache(\n            config('excel.cache.batch.memory_limit', 60000)\n        );\n    }\n\n    /**\n     * @return BatchCache\n     */\n    public function createBatchDriver(): CacheInterface\n    {\n        if (!InstalledVersions::satisfies(new VersionParser, 'psr/simple-cache', '^3.0')) {\n            return new BatchCacheDeprecated(\n                $this->createIlluminateDriver(),\n                $this->createMemoryDriver(),\n                config('excel.cache.default_ttl')\n            );\n        }\n\n        return new BatchCache(\n            $this->createIlluminateDriver(),\n            $this->createMemoryDriver(),\n            config('excel.cache.default_ttl')\n        );\n    }\n\n    /**\n     * @return CacheInterface\n     */\n    public function createIlluminateDriver(): CacheInterface\n    {\n        return Cache::driver(\n            config('excel.cache.illuminate.store')\n        );\n    }\n\n    public function flush()\n    {\n        $this->driver()->clear();\n    }\n\n    public function isInMemory(): bool\n    {\n        return $this->getDefaultDriver() === self::DRIVER_MEMORY;\n    }\n}\n"
  },
  {
    "path": "src/Cache/MemoryCache.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Cache;\n\nuse PhpOffice\\PhpSpreadsheet\\Cell\\Cell;\nuse Psr\\SimpleCache\\CacheInterface;\n\nclass MemoryCache implements CacheInterface\n{\n    /**\n     * @var int|null\n     */\n    protected $memoryLimit;\n\n    /**\n     * @var array\n     */\n    protected $cache = [];\n\n    /**\n     * @param  int|null  $memoryLimit\n     */\n    public function __construct(?int $memoryLimit = null)\n    {\n        $this->memoryLimit = $memoryLimit;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function clear(): bool\n    {\n        $this->cache = [];\n\n        return true;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function delete(string $key): bool\n    {\n        unset($this->cache[$key]);\n\n        return true;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function deleteMultiple($keys): bool\n    {\n        foreach ($keys as $key) {\n            $this->delete($key);\n        }\n\n        return true;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function get(string $key, mixed $default = null): mixed\n    {\n        if ($this->has($key)) {\n            return $this->cache[$key];\n        }\n\n        return $default;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function getMultiple(iterable $keys, mixed $default = null): iterable\n    {\n        $results = [];\n        foreach ($keys as $key) {\n            $results[$key] = $this->get($key, $default);\n        }\n\n        return $results;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function has($key): bool\n    {\n        return isset($this->cache[$key]);\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function set(string $key, mixed $value, null|int|\\DateInterval $ttl = null): bool\n    {\n        $this->cache[$key] = $value;\n\n        return true;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function setMultiple($values, $ttl = null): bool\n    {\n        foreach ($values as $key => $value) {\n            $this->set($key, $value);\n        }\n\n        return true;\n    }\n\n    /**\n     * @return bool\n     */\n    public function reachedMemoryLimit(): bool\n    {\n        // When no limit is given, we'll never reach any limit.\n        if (null === $this->memoryLimit) {\n            return false;\n        }\n\n        return count($this->cache) >= $this->memoryLimit;\n    }\n\n    /**\n     * @return array\n     */\n    public function flush(): array\n    {\n        $memory = $this->cache;\n\n        foreach ($memory as $cell) {\n            if ($cell instanceof Cell) {\n                $cell->detach();\n            }\n        }\n\n        $this->clear();\n\n        return $memory;\n    }\n}\n"
  },
  {
    "path": "src/Cache/MemoryCacheDeprecated.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Cache;\n\nuse PhpOffice\\PhpSpreadsheet\\Cell\\Cell;\nuse Psr\\SimpleCache\\CacheInterface;\n\nclass MemoryCacheDeprecated implements CacheInterface\n{\n    /**\n     * @var int|null\n     */\n    protected $memoryLimit;\n\n    /**\n     * @var array\n     */\n    protected $cache = [];\n\n    /**\n     * @param  int|null  $memoryLimit\n     */\n    public function __construct(?int $memoryLimit = null)\n    {\n        $this->memoryLimit = $memoryLimit;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function clear()\n    {\n        $this->cache = [];\n\n        return true;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function delete($key)\n    {\n        unset($this->cache[$key]);\n\n        return true;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function deleteMultiple($keys)\n    {\n        foreach ($keys as $key) {\n            $this->delete($key);\n        }\n\n        return true;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function get($key, $default = null)\n    {\n        if ($this->has($key)) {\n            return $this->cache[$key];\n        }\n\n        return $default;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function getMultiple($keys, $default = null)\n    {\n        $results = [];\n        foreach ($keys as $key) {\n            $results[$key] = $this->get($key, $default);\n        }\n\n        return $results;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function has($key)\n    {\n        return isset($this->cache[$key]);\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function set($key, $value, $ttl = null)\n    {\n        $this->cache[$key] = $value;\n\n        return true;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function setMultiple($values, $ttl = null)\n    {\n        foreach ($values as $key => $value) {\n            $this->set($key, $value);\n        }\n\n        return true;\n    }\n\n    /**\n     * @return bool\n     */\n    public function reachedMemoryLimit(): bool\n    {\n        // When no limit is given, we'll never reach any limit.\n        if (null === $this->memoryLimit) {\n            return false;\n        }\n\n        return count($this->cache) >= $this->memoryLimit;\n    }\n\n    /**\n     * @return array\n     */\n    public function flush(): array\n    {\n        $memory = $this->cache;\n\n        foreach ($memory as $cell) {\n            if ($cell instanceof Cell) {\n                $cell->detach();\n            }\n        }\n\n        $this->clear();\n\n        return $memory;\n    }\n}\n"
  },
  {
    "path": "src/Cell.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel;\n\nuse Illuminate\\Pipeline\\Pipeline;\nuse PhpOffice\\PhpSpreadsheet\\Calculation\\Exception;\nuse PhpOffice\\PhpSpreadsheet\\Cell\\Cell as SpreadsheetCell;\nuse PhpOffice\\PhpSpreadsheet\\RichText\\RichText;\nuse PhpOffice\\PhpSpreadsheet\\Style\\NumberFormat;\nuse PhpOffice\\PhpSpreadsheet\\Worksheet\\Worksheet;\n\n/** @mixin SpreadsheetCell */\nclass Cell\n{\n    use DelegatedMacroable;\n\n    /**\n     * @var SpreadsheetCell\n     */\n    private $cell;\n\n    /**\n     * @param  SpreadsheetCell  $cell\n     */\n    public function __construct(SpreadsheetCell $cell)\n    {\n        $this->cell = $cell;\n    }\n\n    /**\n     * @param  Worksheet  $worksheet\n     * @param  string  $coordinate\n     * @return Cell\n     *\n     * @throws \\PhpOffice\\PhpSpreadsheet\\Exception\n     */\n    public static function make(Worksheet $worksheet, string $coordinate)\n    {\n        return new static($worksheet->getCell($coordinate));\n    }\n\n    /**\n     * @return SpreadsheetCell\n     */\n    public function getDelegate(): SpreadsheetCell\n    {\n        return $this->cell;\n    }\n\n    /**\n     * @param  null  $nullValue\n     * @param  bool  $calculateFormulas\n     * @param  bool  $formatData\n     * @return mixed\n     */\n    public function getValue($nullValue = null, $calculateFormulas = false, $formatData = true)\n    {\n        $value = $nullValue;\n        if ($this->cell->getValue() !== null) {\n            if ($this->cell->getValue() instanceof RichText) {\n                $value = $this->cell->getValue()->getPlainText();\n            } elseif ($calculateFormulas) {\n                try {\n                    $value = $this->cell->getCalculatedValue();\n                } catch (Exception $e) {\n                    $value = $this->cell->getOldCalculatedValue();\n                }\n            } else {\n                $value = $this->cell->getValue();\n            }\n\n            if ($formatData) {\n                $style = $this->cell->getWorksheet()->getParent()->getCellXfByIndex($this->cell->getXfIndex());\n                $value = NumberFormat::toFormattedString(\n                    $value,\n                    ($style && $style->getNumberFormat()) ? $style->getNumberFormat()->getFormatCode() : NumberFormat::FORMAT_GENERAL\n                );\n            }\n        }\n\n        return app(Pipeline::class)->send($value)->through(config('excel.imports.cells.middleware', []))->thenReturn();\n    }\n}\n"
  },
  {
    "path": "src/ChunkReader.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel;\n\nuse Illuminate\\Bus\\Queueable;\nuse Illuminate\\Container\\Container;\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Illuminate\\Foundation\\Bus\\PendingDispatch;\nuse Illuminate\\Queue\\InteractsWithQueue;\nuse Illuminate\\Queue\\Jobs\\SyncJob;\nuse Illuminate\\Support\\Collection;\nuse Maatwebsite\\Excel\\Concerns\\ShouldQueueWithoutChain;\nuse Maatwebsite\\Excel\\Concerns\\WithChunkReading;\nuse Maatwebsite\\Excel\\Concerns\\WithEvents;\nuse Maatwebsite\\Excel\\Concerns\\WithLimit;\nuse Maatwebsite\\Excel\\Concerns\\WithProgressBar;\nuse Maatwebsite\\Excel\\Files\\TemporaryFile;\nuse Maatwebsite\\Excel\\Imports\\HeadingRowExtractor;\nuse Maatwebsite\\Excel\\Jobs\\AfterImportJob;\nuse Maatwebsite\\Excel\\Jobs\\QueueImport;\nuse Maatwebsite\\Excel\\Jobs\\ReadChunk;\nuse Throwable;\n\nclass ChunkReader\n{\n    /**\n     * @var Container\n     */\n    protected $container;\n\n    public function __construct(Container $container)\n    {\n        $this->container = $container;\n    }\n\n    /**\n     * @param  WithChunkReading  $import\n     * @param  Reader  $reader\n     * @param  TemporaryFile  $temporaryFile\n     * @return PendingDispatch|Collection|null\n     */\n    public function read(WithChunkReading $import, Reader $reader, TemporaryFile $temporaryFile)\n    {\n        if ($import instanceof WithEvents) {\n            $reader->beforeImport($import);\n        }\n\n        $chunkSize    = $import->chunkSize();\n        $totalRows    = $reader->getTotalRows();\n        $worksheets   = $reader->getWorksheets($import);\n        $queue        = property_exists($import, 'queue') ? $import->queue : null;\n        $delayCleanup = property_exists($import, 'cleanupInterval') ? $import->cleanupInterval : 60;\n\n        if ($import instanceof WithProgressBar) {\n            $import->getConsoleOutput()->progressStart(array_sum($totalRows));\n        }\n\n        $jobs = new Collection();\n        foreach ($worksheets as $name => $sheetImport) {\n            $startRow = HeadingRowExtractor::determineStartRow($sheetImport);\n\n            if ($sheetImport instanceof WithLimit) {\n                $limit = $sheetImport->limit();\n\n                if ($limit <= $totalRows[$name]) {\n                    $totalRows[$name] = $sheetImport->limit();\n                }\n            }\n\n            for ($currentRow = $startRow; $currentRow <= $totalRows[$name]; $currentRow += $chunkSize) {\n                $jobs->push(new ReadChunk(\n                    $import,\n                    $reader->getPhpSpreadsheetReader(),\n                    $temporaryFile,\n                    $name,\n                    $sheetImport,\n                    $currentRow,\n                    $chunkSize\n                ));\n            }\n        }\n\n        $afterImportJob = new AfterImportJob($import, $reader);\n\n        if ($import instanceof ShouldQueueWithoutChain) {\n            $afterImportJob->setInterval($delayCleanup);\n            $afterImportJob->setDependencies($jobs);\n            $jobs->push($afterImportJob->delay($delayCleanup));\n\n            return $jobs->each(function ($job) use ($queue) {\n                dispatch($job->onQueue($queue));\n            });\n        }\n\n        $jobs->push($afterImportJob);\n\n        if ($import instanceof ShouldQueue) {\n            return new PendingDispatch(\n                (new QueueImport($import))->chain($jobs->toArray())\n            );\n        }\n\n        $jobs->each(function ($job) {\n            try {\n                function_exists('dispatch_now')\n                    ? dispatch_now($job)\n                    : $this->dispatchNow($job);\n            } catch (Throwable $e) {\n                if (method_exists($job, 'failed')) {\n                    $job->failed($e);\n                }\n                throw $e;\n            }\n        });\n\n        if ($import instanceof WithProgressBar) {\n            $import->getConsoleOutput()->progressFinish();\n        }\n\n        unset($jobs);\n\n        return null;\n    }\n\n    /**\n     * Dispatch a command to its appropriate handler in the current process without using the synchronous queue.\n     *\n     * @param  object  $command\n     * @param  mixed  $handler\n     * @return mixed\n     */\n    protected function dispatchNow($command, $handler = null)\n    {\n        $uses = class_uses_recursive($command);\n\n        if (in_array(InteractsWithQueue::class, $uses) &&\n            in_array(Queueable::class, $uses) && !$command->job\n        ) {\n            $command->setJob(new SyncJob($this->container, json_encode([]), 'sync', 'sync'));\n        }\n\n        $method = method_exists($command, 'handle') ? 'handle' : '__invoke';\n\n        return $this->container->call([$command, $method]);\n    }\n}\n"
  },
  {
    "path": "src/Concerns/Exportable.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\nuse Illuminate\\Foundation\\Bus\\PendingDispatch;\nuse Maatwebsite\\Excel\\Exceptions\\NoFilenameGivenException;\nuse Maatwebsite\\Excel\\Exceptions\\NoFilePathGivenException;\nuse Maatwebsite\\Excel\\Exporter;\n\ntrait Exportable\n{\n    /**\n     * @param  string  $fileName\n     * @param  string|null  $writerType\n     * @param  array  $headers\n     * @return \\Illuminate\\Http\\Response|\\Symfony\\Component\\HttpFoundation\\BinaryFileResponse\n     *\n     * @throws NoFilenameGivenException\n     */\n    public function download(?string $fileName = null, ?string $writerType = null, ?array $headers = null)\n    {\n        $headers    = $headers ?? $this->headers ?? [];\n        $fileName   = $fileName ?? $this->fileName ?? null;\n        $writerType = $writerType ?? $this->writerType ?? null;\n\n        if (null === $fileName) {\n            throw new NoFilenameGivenException();\n        }\n\n        return $this->getExporter()->download($this, $fileName, $writerType, $headers);\n    }\n\n    /**\n     * @param  string  $filePath\n     * @param  string|null  $disk\n     * @param  string|null  $writerType\n     * @param  mixed  $diskOptions\n     * @return bool|PendingDispatch\n     *\n     * @throws NoFilePathGivenException\n     */\n    public function store(?string $filePath = null, ?string $disk = null, ?string $writerType = null, $diskOptions = [])\n    {\n        $filePath = $filePath ?? $this->filePath ?? null;\n\n        if (null === $filePath) {\n            throw NoFilePathGivenException::export();\n        }\n\n        return $this->getExporter()->store(\n            $this,\n            $filePath,\n            $disk ?? $this->disk ?? null,\n            $writerType ?? $this->writerType ?? null,\n            $diskOptions ?: $this->diskOptions ?? []\n        );\n    }\n\n    /**\n     * @param  string|null  $filePath\n     * @param  string|null  $disk\n     * @param  string|null  $writerType\n     * @param  mixed  $diskOptions\n     * @return PendingDispatch\n     *\n     * @throws NoFilePathGivenException\n     */\n    public function queue(?string $filePath = null, ?string $disk = null, ?string $writerType = null, $diskOptions = [])\n    {\n        $filePath = $filePath ?? $this->filePath ?? null;\n\n        if (null === $filePath) {\n            throw NoFilePathGivenException::export();\n        }\n\n        return $this->getExporter()->queue(\n            $this,\n            $filePath,\n            $disk ?? $this->disk ?? null,\n            $writerType ?? $this->writerType ?? null,\n            $diskOptions ?: $this->diskOptions ?? []\n        );\n    }\n\n    /**\n     * @param  string|null  $writerType\n     * @return string\n     */\n    public function raw($writerType = null)\n    {\n        $writerType = $writerType ?? $this->writerType ?? null;\n\n        return $this->getExporter()->raw($this, $writerType);\n    }\n\n    /**\n     * Create an HTTP response that represents the object.\n     *\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @return \\Illuminate\\Http\\Response\n     *\n     * @throws NoFilenameGivenException\n     */\n    public function toResponse($request)\n    {\n        return $this->download();\n    }\n\n    /**\n     * @return Exporter\n     */\n    private function getExporter(): Exporter\n    {\n        return app(Exporter::class);\n    }\n}\n"
  },
  {
    "path": "src/Concerns/FromArray.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\ninterface FromArray\n{\n    /**\n     * @return array\n     */\n    public function array(): array;\n}\n"
  },
  {
    "path": "src/Concerns/FromCollection.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\nuse Illuminate\\Support\\Collection;\n\ninterface FromCollection\n{\n    /**\n     * @return Collection\n     */\n    public function collection();\n}\n"
  },
  {
    "path": "src/Concerns/FromGenerator.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\nuse Generator;\n\ninterface FromGenerator\n{\n    /**\n     * @return Generator\n     */\n    public function generator(): Generator;\n}\n"
  },
  {
    "path": "src/Concerns/FromIterator.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\nuse Iterator;\n\ninterface FromIterator\n{\n    /**\n     * @return Iterator\n     */\n    public function iterator(): Iterator;\n}\n"
  },
  {
    "path": "src/Concerns/FromQuery.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\nuse Illuminate\\Database\\Eloquent\\Builder as EloquentBuilder;\nuse Illuminate\\Database\\Eloquent\\Relations\\Relation;\nuse Illuminate\\Database\\Query\\Builder;\nuse Laravel\\Scout\\Builder as ScoutBuilder;\n\ninterface FromQuery\n{\n    /**\n     * @return Builder|EloquentBuilder|Relation|ScoutBuilder\n     */\n    public function query();\n}\n"
  },
  {
    "path": "src/Concerns/FromView.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\nuse Illuminate\\Contracts\\View\\View;\n\ninterface FromView\n{\n    /**\n     * @return View\n     */\n    public function view(): View;\n}\n"
  },
  {
    "path": "src/Concerns/HasReferencesToOtherSheets.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\ninterface HasReferencesToOtherSheets\n{\n}\n"
  },
  {
    "path": "src/Concerns/Importable.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\nuse Illuminate\\Console\\OutputStyle;\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Illuminate\\Foundation\\Bus\\PendingDispatch;\nuse Illuminate\\Support\\Collection;\nuse InvalidArgumentException;\nuse Maatwebsite\\Excel\\Exceptions\\NoFilePathGivenException;\nuse Maatwebsite\\Excel\\Importer;\nuse Symfony\\Component\\Console\\Input\\StringInput;\nuse Symfony\\Component\\Console\\Output\\NullOutput;\nuse Symfony\\Component\\HttpFoundation\\File\\UploadedFile;\n\ntrait Importable\n{\n    /**\n     * @var OutputStyle|null\n     */\n    protected $output;\n\n    /**\n     * @param  string|UploadedFile|null  $filePath\n     * @param  string|null  $disk\n     * @param  string|null  $readerType\n     * @return Importer|PendingDispatch\n     *\n     * @throws NoFilePathGivenException\n     */\n    public function import($filePath = null, ?string $disk = null, ?string $readerType = null)\n    {\n        $filePath = $this->getFilePath($filePath);\n\n        return $this->getImporter()->import(\n            $this,\n            $filePath,\n            $disk ?? $this->disk ?? null,\n            $readerType ?? $this->readerType ?? null\n        );\n    }\n\n    /**\n     * @param  string|UploadedFile|null  $filePath\n     * @param  string|null  $disk\n     * @param  string|null  $readerType\n     * @return array\n     *\n     * @throws NoFilePathGivenException\n     */\n    public function toArray($filePath = null, ?string $disk = null, ?string $readerType = null): array\n    {\n        $filePath = $this->getFilePath($filePath);\n\n        return $this->getImporter()->toArray(\n            $this,\n            $filePath,\n            $disk ?? $this->disk ?? null,\n            $readerType ?? $this->readerType ?? null\n        );\n    }\n\n    /**\n     * @param  string|UploadedFile|null  $filePath\n     * @param  string|null  $disk\n     * @param  string|null  $readerType\n     * @return Collection\n     *\n     * @throws NoFilePathGivenException\n     */\n    public function toCollection($filePath = null, ?string $disk = null, ?string $readerType = null): Collection\n    {\n        $filePath = $this->getFilePath($filePath);\n\n        return $this->getImporter()->toCollection(\n            $this,\n            $filePath,\n            $disk ?? $this->disk ?? null,\n            $readerType ?? $this->readerType ?? null\n        );\n    }\n\n    /**\n     * @param  string|UploadedFile|null  $filePath\n     * @param  string|null  $disk\n     * @param  string|null  $readerType\n     * @return PendingDispatch\n     *\n     * @throws NoFilePathGivenException\n     * @throws InvalidArgumentException\n     */\n    public function queue($filePath = null, ?string $disk = null, ?string $readerType = null)\n    {\n        if (!$this instanceof ShouldQueue) {\n            throw new InvalidArgumentException('Importable should implement ShouldQueue to be queued.');\n        }\n\n        return $this->import($filePath, $disk, $readerType);\n    }\n\n    /**\n     * @param  OutputStyle  $output\n     * @return $this\n     */\n    public function withOutput(OutputStyle $output)\n    {\n        $this->output = $output;\n\n        return $this;\n    }\n\n    /**\n     * @return OutputStyle\n     */\n    public function getConsoleOutput(): OutputStyle\n    {\n        if (!$this->output instanceof OutputStyle) {\n            $this->output = new OutputStyle(new StringInput(''), new NullOutput());\n        }\n\n        return $this->output;\n    }\n\n    /**\n     * @param  UploadedFile|string|null  $filePath\n     * @return UploadedFile|string\n     *\n     * @throws NoFilePathGivenException\n     */\n    private function getFilePath($filePath = null)\n    {\n        $filePath = $filePath ?? $this->filePath ?? null;\n\n        if (null === $filePath) {\n            throw NoFilePathGivenException::import();\n        }\n\n        return $filePath;\n    }\n\n    /**\n     * @return Importer\n     */\n    private function getImporter(): Importer\n    {\n        return app(Importer::class);\n    }\n}\n"
  },
  {
    "path": "src/Concerns/MapsCsvSettings.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\nuse Illuminate\\Support\\Arr;\n\ntrait MapsCsvSettings\n{\n    /**\n     * @var string\n     */\n    protected static $delimiter = ',';\n\n    /**\n     * @var string\n     */\n    protected static $enclosure = '\"';\n\n    /**\n     * @var string\n     */\n    protected static $lineEnding = PHP_EOL;\n\n    /**\n     * @var bool\n     */\n    protected static $useBom = false;\n\n    /**\n     * @var bool\n     */\n    protected static $includeSeparatorLine = false;\n\n    /**\n     * @var bool\n     */\n    protected static $excelCompatibility = false;\n\n    /**\n     * @var string\n     */\n    protected static $escapeCharacter = '\\\\';\n\n    /**\n     * @var bool\n     */\n    protected static $contiguous = false;\n\n    /**\n     * @var string\n     */\n    protected static $inputEncoding = 'UTF-8';\n\n    /**\n     * @var string\n     */\n    protected static $outputEncoding = '';\n\n    /**\n     * @var bool\n     */\n    protected static $testAutoDetect = true;\n\n    /**\n     * @param  array  $config\n     */\n    public static function applyCsvSettings(array $config)\n    {\n        static::$delimiter            = Arr::get($config, 'delimiter', static::$delimiter);\n        static::$enclosure            = Arr::get($config, 'enclosure', static::$enclosure);\n        static::$lineEnding           = Arr::get($config, 'line_ending', static::$lineEnding);\n        static::$useBom               = Arr::get($config, 'use_bom', static::$useBom);\n        static::$includeSeparatorLine = Arr::get($config, 'include_separator_line', static::$includeSeparatorLine);\n        static::$excelCompatibility   = Arr::get($config, 'excel_compatibility', static::$excelCompatibility);\n        static::$escapeCharacter      = Arr::get($config, 'escape_character', static::$escapeCharacter);\n        static::$contiguous           = Arr::get($config, 'contiguous', static::$contiguous);\n        static::$inputEncoding        = Arr::get($config, 'input_encoding', static::$inputEncoding);\n        static::$outputEncoding       = Arr::get($config, 'output_encoding', static::$outputEncoding);\n        static::$testAutoDetect       = Arr::get($config, 'test_auto_detect', static::$testAutoDetect);\n    }\n}\n"
  },
  {
    "path": "src/Concerns/OnEachRow.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\nuse Maatwebsite\\Excel\\Row;\n\ninterface OnEachRow\n{\n    /**\n     * @param  Row  $row\n     */\n    public function onRow(Row $row);\n}\n"
  },
  {
    "path": "src/Concerns/PersistRelations.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\ninterface PersistRelations\n{\n}\n"
  },
  {
    "path": "src/Concerns/RegistersEventListeners.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\nuse Maatwebsite\\Excel\\Events\\AfterBatch;\nuse Maatwebsite\\Excel\\Events\\AfterChunk;\nuse Maatwebsite\\Excel\\Events\\AfterImport;\nuse Maatwebsite\\Excel\\Events\\AfterSheet;\nuse Maatwebsite\\Excel\\Events\\BeforeExport;\nuse Maatwebsite\\Excel\\Events\\BeforeImport;\nuse Maatwebsite\\Excel\\Events\\BeforeSheet;\nuse Maatwebsite\\Excel\\Events\\BeforeWriting;\nuse Maatwebsite\\Excel\\Events\\ImportFailed;\n\ntrait RegistersEventListeners\n{\n    /**\n     * @return array\n     */\n    public function registerEvents(): array\n    {\n        $listenersClasses = [\n            BeforeExport::class  => 'beforeExport',\n            BeforeWriting::class => 'beforeWriting',\n            BeforeImport::class  => 'beforeImport',\n            AfterImport::class   => 'afterImport',\n            AfterBatch::class    => 'afterBatch',\n            AfterChunk::class    => 'afterChunk',\n            ImportFailed::class  => 'importFailed',\n            BeforeSheet::class   => 'beforeSheet',\n            AfterSheet::class    => 'afterSheet',\n        ];\n        $listeners = [];\n\n        foreach ($listenersClasses as $class => $name) {\n            // Method names are case insensitive in php\n            if (method_exists($this, $name)) {\n                // Allow methods to not be static\n                $listeners[$class] = [$this, $name];\n            }\n        }\n\n        return $listeners;\n    }\n}\n"
  },
  {
    "path": "src/Concerns/RemembersChunkOffset.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\ntrait RemembersChunkOffset\n{\n    /**\n     * @var int|null\n     */\n    protected $chunkOffset;\n\n    /**\n     * @param  int  $chunkOffset\n     */\n    public function setChunkOffset(int $chunkOffset)\n    {\n        $this->chunkOffset = $chunkOffset;\n    }\n\n    /**\n     * @return int|null\n     */\n    public function getChunkOffset()\n    {\n        return $this->chunkOffset;\n    }\n}\n"
  },
  {
    "path": "src/Concerns/RemembersRowNumber.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\ntrait RemembersRowNumber\n{\n    /**\n     * @var int\n     */\n    protected $rowNumber;\n\n    /**\n     * @param  int  $rowNumber\n     */\n    public function rememberRowNumber(int $rowNumber)\n    {\n        $this->rowNumber = $rowNumber;\n    }\n\n    /**\n     * @return int|null\n     */\n    public function getRowNumber()\n    {\n        return $this->rowNumber;\n    }\n}\n"
  },
  {
    "path": "src/Concerns/ShouldAutoSize.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\ninterface ShouldAutoSize\n{\n}\n"
  },
  {
    "path": "src/Concerns/ShouldQueueWithoutChain.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\n\ninterface ShouldQueueWithoutChain extends ShouldQueue\n{\n}\n"
  },
  {
    "path": "src/Concerns/SkipsEmptyRows.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\ninterface SkipsEmptyRows\n{\n}\n"
  },
  {
    "path": "src/Concerns/SkipsErrors.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\nuse Illuminate\\Support\\Collection;\nuse Throwable;\n\ntrait SkipsErrors\n{\n    /**\n     * @var Throwable[]\n     */\n    protected $errors = [];\n\n    /**\n     * @param  Throwable  $e\n     */\n    public function onError(Throwable $e)\n    {\n        $this->errors[] = $e;\n    }\n\n    /**\n     * @return Throwable[]|Collection\n     */\n    public function errors(): Collection\n    {\n        return new Collection($this->errors);\n    }\n}\n"
  },
  {
    "path": "src/Concerns/SkipsFailures.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\nuse Illuminate\\Support\\Collection;\nuse Maatwebsite\\Excel\\Validators\\Failure;\n\ntrait SkipsFailures\n{\n    /**\n     * @var Failure[]\n     */\n    protected $failures = [];\n\n    /**\n     * @param  Failure  ...$failures\n     */\n    public function onFailure(Failure ...$failures)\n    {\n        $this->failures = array_merge($this->failures, $failures);\n    }\n\n    /**\n     * @return Failure[]|Collection\n     */\n    public function failures(): Collection\n    {\n        return new Collection($this->failures);\n    }\n}\n"
  },
  {
    "path": "src/Concerns/SkipsOnError.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\nuse Throwable;\n\ninterface SkipsOnError\n{\n    /**\n     * @param  Throwable  $e\n     */\n    public function onError(Throwable $e);\n}\n"
  },
  {
    "path": "src/Concerns/SkipsOnFailure.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\nuse Maatwebsite\\Excel\\Validators\\Failure;\n\ninterface SkipsOnFailure\n{\n    /**\n     * @param  Failure[]  $failures\n     */\n    public function onFailure(Failure ...$failures);\n}\n"
  },
  {
    "path": "src/Concerns/SkipsUnknownSheets.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\ninterface SkipsUnknownSheets\n{\n    /**\n     * @param  string|int  $sheetName\n     */\n    public function onUnknownSheet($sheetName);\n}\n"
  },
  {
    "path": "src/Concerns/ToArray.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\ninterface ToArray\n{\n    /**\n     * @param  array  $array\n     */\n    public function array(array $array);\n}\n"
  },
  {
    "path": "src/Concerns/ToCollection.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\nuse Illuminate\\Support\\Collection;\n\ninterface ToCollection\n{\n    /**\n     * @param  Collection  $collection\n     */\n    public function collection(Collection $collection);\n}\n"
  },
  {
    "path": "src/Concerns/ToModel.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\nuse Illuminate\\Database\\Eloquent\\Model;\n\ninterface ToModel\n{\n    /**\n     * @param  array  $row\n     * @return Model|Model[]|null\n     */\n    public function model(array $row);\n}\n"
  },
  {
    "path": "src/Concerns/WithBackgroundColor.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\nuse PhpOffice\\PhpSpreadsheet\\Style\\Color;\n\ninterface WithBackgroundColor\n{\n    /**\n     * @return string|array|Color\n     */\n    public function backgroundColor();\n}\n"
  },
  {
    "path": "src/Concerns/WithBatchInserts.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\ninterface WithBatchInserts\n{\n    /**\n     * @return int\n     */\n    public function batchSize(): int;\n}\n"
  },
  {
    "path": "src/Concerns/WithCalculatedFormulas.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\ninterface WithCalculatedFormulas\n{\n}\n"
  },
  {
    "path": "src/Concerns/WithCharts.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\nuse PhpOffice\\PhpSpreadsheet\\Chart\\Chart;\n\ninterface WithCharts\n{\n    /**\n     * @return Chart|Chart[]\n     */\n    public function charts();\n}\n"
  },
  {
    "path": "src/Concerns/WithChunkReading.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\ninterface WithChunkReading\n{\n    /**\n     * @return int\n     */\n    public function chunkSize(): int;\n}\n"
  },
  {
    "path": "src/Concerns/WithColumnFormatting.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\ninterface WithColumnFormatting\n{\n    /**\n     * @return array\n     */\n    public function columnFormats(): array;\n}\n"
  },
  {
    "path": "src/Concerns/WithColumnLimit.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\ninterface WithColumnLimit\n{\n    public function endColumn(): string;\n}\n"
  },
  {
    "path": "src/Concerns/WithColumnWidths.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\ninterface WithColumnWidths\n{\n    public function columnWidths(): array;\n}\n"
  },
  {
    "path": "src/Concerns/WithConditionalSheets.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\ntrait WithConditionalSheets\n{\n    /**\n     * @var array\n     */\n    protected $conditionallySelectedSheets = [];\n\n    /**\n     * @param  string|array  $sheets\n     * @return $this\n     */\n    public function onlySheets($sheets)\n    {\n        $this->conditionallySelectedSheets = is_array($sheets) ? $sheets : func_get_args();\n\n        return $this;\n    }\n\n    /**\n     * @return array\n     */\n    public function sheets(): array\n    {\n        return \\array_filter($this->conditionalSheets(), function ($name) {\n            return \\in_array($name, $this->conditionallySelectedSheets, false);\n        }, ARRAY_FILTER_USE_KEY);\n    }\n\n    /**\n     * @return array\n     */\n    abstract public function conditionalSheets(): array;\n}\n"
  },
  {
    "path": "src/Concerns/WithCustomChunkSize.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\ninterface WithCustomChunkSize\n{\n    /**\n     * @return int\n     */\n    public function chunkSize(): int;\n}\n"
  },
  {
    "path": "src/Concerns/WithCustomCsvSettings.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\ninterface WithCustomCsvSettings\n{\n    /**\n     * @return array\n     */\n    public function getCsvSettings(): array;\n}\n"
  },
  {
    "path": "src/Concerns/WithCustomQuerySize.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\ninterface WithCustomQuerySize\n{\n    /**\n     * Queued exportables are processed in chunks; each chunk being a job pushed to the queue by the QueuedWriter.\n     * In case of exportables that implement the FromQuery concern, the number of jobs is calculated by dividing the $query->count() by the chunk size.\n     * Depending on the implementation of the query() method (eg. When using a groupBy clause), this calculation might not be correct.\n     *\n     * When this is the case, you should use this method to provide a custom calculation of the query size.\n     *\n     * @return int\n     */\n    public function querySize(): int;\n}\n"
  },
  {
    "path": "src/Concerns/WithCustomStartCell.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\ninterface WithCustomStartCell\n{\n    /**\n     * @return string\n     */\n    public function startCell(): string;\n}\n"
  },
  {
    "path": "src/Concerns/WithCustomValueBinder.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\nuse PhpOffice\\PhpSpreadsheet\\Cell\\IValueBinder;\n\ninterface WithCustomValueBinder extends IValueBinder\n{\n}\n"
  },
  {
    "path": "src/Concerns/WithDefaultStyles.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\nuse PhpOffice\\PhpSpreadsheet\\Style\\Style;\n\ninterface WithDefaultStyles\n{\n    /**\n     * @return array|void\n     */\n    public function defaultStyles(Style $defaultStyle);\n}\n"
  },
  {
    "path": "src/Concerns/WithDrawings.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\nuse PhpOffice\\PhpSpreadsheet\\Worksheet\\BaseDrawing;\n\ninterface WithDrawings\n{\n    /**\n     * @return BaseDrawing|BaseDrawing[]\n     */\n    public function drawings();\n}\n"
  },
  {
    "path": "src/Concerns/WithEvents.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\ninterface WithEvents\n{\n    /**\n     * @return array\n     */\n    public function registerEvents(): array;\n}\n"
  },
  {
    "path": "src/Concerns/WithFormatData.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\ninterface WithFormatData\n{\n}\n"
  },
  {
    "path": "src/Concerns/WithGroupedHeadingRow.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\ninterface WithGroupedHeadingRow extends WithHeadingRow\n{\n}\n"
  },
  {
    "path": "src/Concerns/WithHeadingRow.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\ninterface WithHeadingRow\n{\n}\n"
  },
  {
    "path": "src/Concerns/WithHeadings.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\ninterface WithHeadings\n{\n    /**\n     * @return array\n     */\n    public function headings(): array;\n}\n"
  },
  {
    "path": "src/Concerns/WithLimit.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\ninterface WithLimit\n{\n    /**\n     * @return int\n     */\n    public function limit(): int;\n}\n"
  },
  {
    "path": "src/Concerns/WithMappedCells.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\ninterface WithMappedCells\n{\n    /**\n     * @return array\n     */\n    public function mapping(): array;\n}\n"
  },
  {
    "path": "src/Concerns/WithMapping.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\n/**\n * @template RowType of mixed\n */\ninterface WithMapping\n{\n    /**\n     * @param  RowType  $row\n     * @return array\n     */\n    public function map($row): array;\n}\n"
  },
  {
    "path": "src/Concerns/WithMultipleSheets.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\ninterface WithMultipleSheets\n{\n    /**\n     * @return array\n     */\n    public function sheets(): array;\n}\n"
  },
  {
    "path": "src/Concerns/WithPreCalculateFormulas.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\ninterface WithPreCalculateFormulas\n{\n}\n"
  },
  {
    "path": "src/Concerns/WithProgressBar.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\nuse Illuminate\\Console\\OutputStyle;\n\ninterface WithProgressBar\n{\n    /**\n     * @return OutputStyle\n     */\n    public function getConsoleOutput(): OutputStyle;\n}\n"
  },
  {
    "path": "src/Concerns/WithProperties.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\ninterface WithProperties\n{\n    public function properties(): array;\n}\n"
  },
  {
    "path": "src/Concerns/WithReadFilter.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\nuse PhpOffice\\PhpSpreadsheet\\Reader\\IReadFilter;\n\ninterface WithReadFilter\n{\n    /**\n     * @return IReadFilter\n     */\n    public function readFilter(): IReadFilter;\n}\n"
  },
  {
    "path": "src/Concerns/WithSkipDuplicates.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\ninterface WithSkipDuplicates\n{\n}\n"
  },
  {
    "path": "src/Concerns/WithStartRow.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\ninterface WithStartRow\n{\n    /**\n     * @return int\n     */\n    public function startRow(): int;\n}\n"
  },
  {
    "path": "src/Concerns/WithStrictNullComparison.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\ninterface WithStrictNullComparison\n{\n}\n"
  },
  {
    "path": "src/Concerns/WithStyles.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\nuse PhpOffice\\PhpSpreadsheet\\Worksheet\\Worksheet;\n\ninterface WithStyles\n{\n    public function styles(Worksheet $sheet);\n}\n"
  },
  {
    "path": "src/Concerns/WithTitle.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\ninterface WithTitle\n{\n    /**\n     * @return string\n     */\n    public function title(): string;\n}\n"
  },
  {
    "path": "src/Concerns/WithUpsertColumns.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\ninterface WithUpsertColumns\n{\n    /**\n     * @return array\n     */\n    public function upsertColumns();\n}\n"
  },
  {
    "path": "src/Concerns/WithUpserts.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\ninterface WithUpserts\n{\n    /**\n     * @return string|array\n     */\n    public function uniqueBy();\n}\n"
  },
  {
    "path": "src/Concerns/WithValidation.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Concerns;\n\ninterface WithValidation\n{\n    /**\n     * @return array\n     */\n    public function rules(): array;\n}\n"
  },
  {
    "path": "src/Console/ExportMakeCommand.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Console;\n\nuse Illuminate\\Console\\GeneratorCommand;\nuse Symfony\\Component\\Console\\Input\\InputOption;\n\nclass ExportMakeCommand extends GeneratorCommand\n{\n    use WithModelStub;\n\n    /**\n     * The console command name.\n     *\n     * @var string\n     */\n    protected $name = 'make:export';\n\n    /**\n     * The console command description.\n     *\n     * @var string\n     */\n    protected $description = 'Create a new export class';\n\n    /**\n     * The type of class being generated.\n     *\n     * @var string\n     */\n    protected $type = 'Export';\n\n    /**\n     * Get the stub file for the generator.\n     *\n     * @return string\n     */\n    protected function getStub()\n    {\n        if ($this->option('model') && $this->option('query')) {\n            return $this->resolveStubPath('/stubs/export.query-model.stub');\n        } elseif ($this->option('model')) {\n            return $this->resolveStubPath('/stubs/export.model.stub');\n        } elseif ($this->option('query')) {\n            return $this->resolveStubPath('/stubs/export.query.stub');\n        }\n\n        return $this->resolveStubPath('/stubs/export.plain.stub');\n    }\n\n    /**\n     * Get the default namespace for the class.\n     *\n     * @param  string  $rootNamespace\n     * @return string\n     */\n    protected function getDefaultNamespace($rootNamespace)\n    {\n        return $rootNamespace . '\\Exports';\n    }\n\n    /**\n     * Build the class with the given name.\n     * Remove the base controller import if we are already in base namespace.\n     *\n     * @param  string  $name\n     * @return string\n     */\n    protected function buildClass($name)\n    {\n        $replace = [];\n        if ($this->option('model')) {\n            $replace = $this->buildModelReplacements($replace);\n        }\n\n        return str_replace(\n            array_keys($replace), array_values($replace), parent::buildClass($name)\n        );\n    }\n\n    /**\n     * Get the console command options.\n     *\n     * @return array\n     */\n    protected function getOptions()\n    {\n        return [\n            ['model', 'm', InputOption::VALUE_OPTIONAL, 'Generate an export for the given model.'],\n            ['query', '', InputOption::VALUE_NONE, 'Generate an export for a query.'],\n        ];\n    }\n}\n"
  },
  {
    "path": "src/Console/ImportMakeCommand.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Console;\n\nuse Illuminate\\Console\\GeneratorCommand;\nuse Symfony\\Component\\Console\\Input\\InputOption;\n\nclass ImportMakeCommand extends GeneratorCommand\n{\n    use WithModelStub;\n\n    /**\n     * The console command name.\n     *\n     * @var string\n     */\n    protected $name = 'make:import';\n\n    /**\n     * The console command description.\n     *\n     * @var string\n     */\n    protected $description = 'Create a new import class';\n\n    /**\n     * The type of class being generated.\n     *\n     * @var string\n     */\n    protected $type = 'Import';\n\n    /**\n     * Get the stub file for the generator.\n     *\n     * @return string\n     */\n    protected function getStub()\n    {\n        return $this->option('model')\n            ? $this->resolveStubPath('/stubs/import.model.stub')\n            : $this->resolveStubPath('/stubs/import.collection.stub');\n    }\n\n    /**\n     * Get the default namespace for the class.\n     *\n     * @param  string  $rootNamespace\n     * @return string\n     */\n    protected function getDefaultNamespace($rootNamespace)\n    {\n        return $rootNamespace . '\\Imports';\n    }\n\n    /**\n     * Build the class with the given name.\n     * Remove the base controller import if we are already in base namespace.\n     *\n     * @param  string  $name\n     * @return string\n     */\n    protected function buildClass($name)\n    {\n        $replace = [];\n        if ($this->option('model')) {\n            $replace = $this->buildModelReplacements($replace);\n        }\n\n        return str_replace(\n            array_keys($replace), array_values($replace), parent::buildClass($name)\n        );\n    }\n\n    /**\n     * Get the console command options.\n     *\n     * @return array\n     */\n    protected function getOptions()\n    {\n        return [\n            ['model', 'm', InputOption::VALUE_OPTIONAL, 'Generate an import for the given model.'],\n        ];\n    }\n}\n"
  },
  {
    "path": "src/Console/WithModelStub.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Console;\n\nuse Illuminate\\Support\\Str;\nuse InvalidArgumentException;\n\ntrait WithModelStub\n{\n    /**\n     * Build the model replacement values.\n     *\n     * @param  array  $replace\n     * @return array\n     */\n    protected function buildModelReplacements(array $replace): array\n    {\n        $modelClass = $this->parseModel($this->option('model'));\n\n        return array_merge($replace, [\n            'DummyFullModelClass' => $modelClass,\n            'DummyModelClass'     => class_basename($modelClass),\n        ]);\n    }\n\n    /**\n     * Get the fully-qualified model class name.\n     *\n     * @param  string  $model\n     * @return string\n     */\n    protected function parseModel($model): string\n    {\n        if (preg_match('([^A-Za-z0-9_/\\\\\\\\])', $model)) {\n            throw new InvalidArgumentException('Model name contains invalid characters.');\n        }\n\n        $model = ltrim($model, '\\\\/');\n\n        $model = str_replace('/', '\\\\', $model);\n\n        $rootNamespace = $this->rootNamespace();\n\n        if (Str::startsWith($model, $rootNamespace)) {\n            return $model;\n        }\n\n        $model = is_dir(app_path('Models'))\n            ? $rootNamespace . 'Models\\\\' . $model\n            : $rootNamespace . $model;\n\n        return $model;\n    }\n\n    /**\n     * Resolve the fully-qualified path to the stub.\n     *\n     * @param  string  $stub\n     * @return string\n     */\n    protected function resolveStubPath($stub)\n    {\n        return file_exists($customPath = $this->laravel->basePath(trim($stub, '/')))\n            ? $customPath\n            : __DIR__ . $stub;\n    }\n}\n"
  },
  {
    "path": "src/Console/stubs/export.model.stub",
    "content": "<?php\n\nnamespace DummyNamespace;\n\nuse DummyFullModelClass;\nuse Maatwebsite\\Excel\\Concerns\\FromCollection;\n\nclass DummyClass implements FromCollection\n{\n    /**\n    * @return \\Illuminate\\Support\\Collection\n    */\n    public function collection()\n    {\n        return DummyModelClass::all();\n    }\n}\n"
  },
  {
    "path": "src/Console/stubs/export.plain.stub",
    "content": "<?php\n\nnamespace DummyNamespace;\n\nuse Maatwebsite\\Excel\\Concerns\\FromCollection;\n\nclass DummyClass implements FromCollection\n{\n    /**\n    * @return \\Illuminate\\Support\\Collection\n    */\n    public function collection()\n    {\n        //\n    }\n}\n"
  },
  {
    "path": "src/Console/stubs/export.query-model.stub",
    "content": "<?php\n\nnamespace DummyNamespace;\n\nuse DummyFullModelClass;\nuse Maatwebsite\\Excel\\Concerns\\FromQuery;\n\nclass DummyClass implements FromQuery\n{\n    /**\n    * @return \\Illuminate\\Database\\Query\\Builder\n    */\n    public function query()\n    {\n        return DummyModelClass::query();\n    }\n}\n"
  },
  {
    "path": "src/Console/stubs/export.query.stub",
    "content": "<?php\n\nnamespace DummyNamespace;\n\nuse Maatwebsite\\Excel\\Concerns\\FromQuery;\n\nclass DummyClass implements FromQuery\n{\n    /**\n    * @return \\Illuminate\\Database\\Query\\Builder\n    */\n    public function query()\n    {\n        //\n    }\n}\n"
  },
  {
    "path": "src/Console/stubs/import.collection.stub",
    "content": "<?php\n\nnamespace DummyNamespace;\n\nuse Illuminate\\Support\\Collection;\nuse Maatwebsite\\Excel\\Concerns\\ToCollection;\n\nclass DummyClass implements ToCollection\n{\n    /**\n    * @param Collection $collection\n    */\n    public function collection(Collection $collection)\n    {\n        //\n    }\n}\n"
  },
  {
    "path": "src/Console/stubs/import.model.stub",
    "content": "<?php\n\nnamespace DummyNamespace;\n\nuse DummyFullModelClass;\nuse Maatwebsite\\Excel\\Concerns\\ToModel;\n\nclass DummyClass implements ToModel\n{\n    /**\n    * @param array $row\n    *\n    * @return \\Illuminate\\Database\\Eloquent\\Model|null\n    */\n    public function model(array $row)\n    {\n        return new DummyModelClass([\n            //\n        ]);\n    }\n}\n"
  },
  {
    "path": "src/DefaultValueBinder.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel;\n\nuse PhpOffice\\PhpSpreadsheet\\Cell\\Cell;\nuse PhpOffice\\PhpSpreadsheet\\Cell\\DefaultValueBinder as PhpSpreadsheetDefaultValueBinder;\n\nclass DefaultValueBinder extends PhpSpreadsheetDefaultValueBinder\n{\n    /**\n     * @param  Cell  $cell  Cell to bind value to\n     * @param  mixed  $value  Value to bind in cell\n     * @return bool\n     */\n    public function bindValue(Cell $cell, $value)\n    {\n        if (is_array($value)) {\n            $value = \\json_encode($value);\n        }\n\n        return parent::bindValue($cell, $value);\n    }\n}\n"
  },
  {
    "path": "src/DelegatedMacroable.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel;\n\nuse Illuminate\\Support\\Traits\\Macroable;\n\ntrait DelegatedMacroable\n{\n    use Macroable {\n        __call as __callMacro;\n    }\n\n    /**\n     * Dynamically handle calls to the class.\n     *\n     * @param  string  $method\n     * @param  array  $parameters\n     * @return mixed\n     */\n    public function __call($method, $parameters)\n    {\n        if (method_exists($this->getDelegate(), $method)) {\n            return call_user_func_array([$this->getDelegate(), $method], $parameters);\n        }\n\n        array_unshift($parameters, $this);\n\n        return $this->__callMacro($method, $parameters);\n    }\n\n    /**\n     * @return object\n     */\n    abstract public function getDelegate();\n}\n"
  },
  {
    "path": "src/Events/AfterBatch.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Events;\n\nuse Maatwebsite\\Excel\\Imports\\ModelManager;\n\nclass AfterBatch extends Event\n{\n    /**\n     * @var ModelManager\n     */\n    public $manager;\n\n    /**\n     * @var int\n     */\n    private $batchSize;\n\n    /**\n     * @var int\n     */\n    private $startRow;\n\n    /**\n     * @param  ModelManager  $manager\n     * @param  object  $importable\n     * @param  int  $batchSize\n     * @param  int  $startRow\n     */\n    public function __construct(ModelManager $manager, $importable, int $batchSize, int $startRow)\n    {\n        $this->manager   = $manager;\n        $this->batchSize = $batchSize;\n        $this->startRow  = $startRow;\n        parent::__construct($importable);\n    }\n\n    public function getManager(): ModelManager\n    {\n        return $this->manager;\n    }\n\n    /**\n     * @return mixed\n     */\n    public function getDelegate()\n    {\n        return $this->manager;\n    }\n\n    public function getBatchSize(): int\n    {\n        return $this->batchSize;\n    }\n\n    public function getStartRow(): int\n    {\n        return $this->startRow;\n    }\n}\n"
  },
  {
    "path": "src/Events/AfterChunk.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Events;\n\nuse Maatwebsite\\Excel\\Sheet;\n\nclass AfterChunk extends Event\n{\n    /**\n     * @var Sheet\n     */\n    private $sheet;\n\n    /**\n     * @var int\n     */\n    private $startRow;\n\n    public function __construct(Sheet $sheet, $importable, int $startRow)\n    {\n        $this->sheet     = $sheet;\n        $this->startRow  = $startRow;\n        parent::__construct($importable);\n    }\n\n    public function getSheet(): Sheet\n    {\n        return $this->sheet;\n    }\n\n    public function getDelegate()\n    {\n        return $this->sheet;\n    }\n\n    public function getStartRow(): int\n    {\n        return $this->startRow;\n    }\n}\n"
  },
  {
    "path": "src/Events/AfterImport.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Events;\n\nuse Maatwebsite\\Excel\\Reader;\n\nclass AfterImport extends Event\n{\n    /**\n     * @var Reader\n     */\n    public $reader;\n\n    /**\n     * @param  Reader  $reader\n     * @param  object  $importable\n     */\n    public function __construct(Reader $reader, $importable)\n    {\n        $this->reader     = $reader;\n        parent::__construct($importable);\n    }\n\n    /**\n     * @return Reader\n     */\n    public function getReader(): Reader\n    {\n        return $this->reader;\n    }\n\n    /**\n     * @return mixed\n     */\n    public function getDelegate()\n    {\n        return $this->reader;\n    }\n}\n"
  },
  {
    "path": "src/Events/AfterSheet.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Events;\n\nuse Maatwebsite\\Excel\\Sheet;\n\nclass AfterSheet extends Event\n{\n    /**\n     * @var Sheet\n     */\n    public $sheet;\n\n    /**\n     * @param  Sheet  $sheet\n     * @param  object  $exportable\n     */\n    public function __construct(Sheet $sheet, $exportable)\n    {\n        $this->sheet      = $sheet;\n        parent::__construct($exportable);\n    }\n\n    /**\n     * @return Sheet\n     */\n    public function getSheet(): Sheet\n    {\n        return $this->sheet;\n    }\n\n    /**\n     * @return mixed\n     */\n    public function getDelegate()\n    {\n        return $this->sheet;\n    }\n}\n"
  },
  {
    "path": "src/Events/BeforeExport.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Events;\n\nuse Maatwebsite\\Excel\\Writer;\n\nclass BeforeExport extends Event\n{\n    /**\n     * @var Writer\n     */\n    public $writer;\n\n    /**\n     * @param  Writer  $writer\n     * @param  object  $exportable\n     */\n    public function __construct(Writer $writer, $exportable)\n    {\n        $this->writer     = $writer;\n        parent::__construct($exportable);\n    }\n\n    /**\n     * @return Writer\n     */\n    public function getWriter(): Writer\n    {\n        return $this->writer;\n    }\n\n    /**\n     * @return mixed\n     */\n    public function getDelegate()\n    {\n        return $this->writer;\n    }\n}\n"
  },
  {
    "path": "src/Events/BeforeImport.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Events;\n\nuse Maatwebsite\\Excel\\Reader;\n\nclass BeforeImport extends Event\n{\n    /**\n     * @var Reader\n     */\n    public $reader;\n\n    /**\n     * @param  Reader  $reader\n     * @param  object  $importable\n     */\n    public function __construct(Reader $reader, $importable)\n    {\n        $this->reader     = $reader;\n        parent::__construct($importable);\n    }\n\n    /**\n     * @return Reader\n     */\n    public function getReader(): Reader\n    {\n        return $this->reader;\n    }\n\n    /**\n     * @return mixed\n     */\n    public function getDelegate()\n    {\n        return $this->reader;\n    }\n}\n"
  },
  {
    "path": "src/Events/BeforeSheet.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Events;\n\nuse Maatwebsite\\Excel\\Sheet;\n\nclass BeforeSheet extends Event\n{\n    /**\n     * @var Sheet\n     */\n    public $sheet;\n\n    /**\n     * @param  Sheet  $sheet\n     * @param  object  $exportable\n     */\n    public function __construct(Sheet $sheet, $exportable)\n    {\n        $this->sheet       = $sheet;\n        parent::__construct($exportable);\n    }\n\n    /**\n     * @return Sheet\n     */\n    public function getSheet(): Sheet\n    {\n        return $this->sheet;\n    }\n\n    /**\n     * @return mixed\n     */\n    public function getDelegate()\n    {\n        return $this->sheet;\n    }\n}\n"
  },
  {
    "path": "src/Events/BeforeWriting.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Events;\n\nuse Maatwebsite\\Excel\\Writer;\n\nclass BeforeWriting extends Event\n{\n    /**\n     * @var Writer\n     */\n    public $writer;\n\n    /**\n     * @var object\n     */\n    private $exportable;\n\n    /**\n     * @param  Writer  $writer\n     * @param  object  $exportable\n     */\n    public function __construct(Writer $writer, $exportable)\n    {\n        $this->writer     = $writer;\n        parent::__construct($exportable);\n    }\n\n    /**\n     * @return Writer\n     */\n    public function getWriter(): Writer\n    {\n        return $this->writer;\n    }\n\n    /**\n     * @return mixed\n     */\n    public function getDelegate()\n    {\n        return $this->writer;\n    }\n}\n"
  },
  {
    "path": "src/Events/Event.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Events;\n\n/**\n * @internal\n */\nabstract class Event\n{\n    /**\n     * @var object\n     */\n    protected $concernable;\n\n    /**\n     * @param  object  $concernable\n     */\n    public function __construct($concernable)\n    {\n        $this->concernable = $concernable;\n    }\n\n    /**\n     * @return object\n     */\n    public function getConcernable()\n    {\n        return $this->concernable;\n    }\n\n    /**\n     * @return mixed\n     */\n    abstract public function getDelegate();\n\n    /**\n     * @param  string  $concern\n     * @return bool\n     */\n    public function appliesToConcern(string $concern): bool\n    {\n        return $this->getConcernable() instanceof $concern;\n    }\n}\n"
  },
  {
    "path": "src/Events/ImportFailed.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Events;\n\nuse Throwable;\n\nclass ImportFailed\n{\n    /**\n     * @var Throwable\n     */\n    public $e;\n\n    /**\n     * @param  Throwable  $e\n     */\n    public function __construct(Throwable $e)\n    {\n        $this->e = $e;\n    }\n\n    /**\n     * @return Throwable\n     */\n    public function getException(): Throwable\n    {\n        return $this->e;\n    }\n}\n"
  },
  {
    "path": "src/Excel.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel;\n\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Illuminate\\Foundation\\Bus\\PendingDispatch;\nuse Illuminate\\Support\\Collection;\nuse Illuminate\\Support\\Traits\\Macroable;\nuse Maatwebsite\\Excel\\Files\\Filesystem;\nuse Maatwebsite\\Excel\\Files\\TemporaryFile;\nuse Maatwebsite\\Excel\\Helpers\\FileTypeDetector;\n\nclass Excel implements Exporter, Importer\n{\n    use Macroable, RegistersCustomConcerns;\n\n    const XLSX     = 'Xlsx';\n\n    const CSV      = 'Csv';\n\n    const TSV      = 'Csv';\n\n    const ODS      = 'Ods';\n\n    const XLS      = 'Xls';\n\n    const SLK      = 'Slk';\n\n    const XML      = 'Xml';\n\n    const GNUMERIC = 'Gnumeric';\n\n    const HTML     = 'Html';\n\n    const MPDF     = 'Mpdf';\n\n    const DOMPDF   = 'Dompdf';\n\n    const TCPDF    = 'Tcpdf';\n\n    /**\n     * @var Writer\n     */\n    protected $writer;\n\n    /**\n     * @var QueuedWriter\n     */\n    protected $queuedWriter;\n\n    /**\n     * @var Filesystem\n     */\n    protected $filesystem;\n\n    /**\n     * @var Reader\n     */\n    private $reader;\n\n    /**\n     * @param  Writer  $writer\n     * @param  QueuedWriter  $queuedWriter\n     * @param  Reader  $reader\n     * @param  Filesystem  $filesystem\n     */\n    public function __construct(\n        Writer $writer,\n        QueuedWriter $queuedWriter,\n        Reader $reader,\n        Filesystem $filesystem\n    ) {\n        $this->writer       = $writer;\n        $this->reader       = $reader;\n        $this->filesystem   = $filesystem;\n        $this->queuedWriter = $queuedWriter;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function download($export, string $fileName, ?string $writerType = null, array $headers = [])\n    {\n        // Clear output buffer to prevent stuff being prepended to the Excel output.\n        if (ob_get_length() > 0) {\n            ob_end_clean();\n            ob_start();\n        }\n\n        return response()->download(\n            $this->export($export, $fileName, $writerType)->getLocalPath(),\n            $fileName,\n            $headers\n        )->deleteFileAfterSend(true);\n    }\n\n    /**\n     * {@inheritdoc}\n     *\n     * @param  string|null  $disk  Fallback for usage with named properties\n     */\n    public function store($export, string $filePath, ?string $diskName = null, ?string $writerType = null, $diskOptions = [], ?string $disk = null)\n    {\n        if ($export instanceof ShouldQueue) {\n            return $this->queue($export, $filePath, $diskName ?: $disk, $writerType, $diskOptions);\n        }\n\n        $temporaryFile = $this->export($export, $filePath, $writerType);\n\n        $exported = $this->filesystem->disk($diskName ?: $disk, $diskOptions)->copy(\n            $temporaryFile,\n            $filePath\n        );\n\n        $temporaryFile->delete();\n\n        return $exported;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function queue($export, string $filePath, ?string $disk = null, ?string $writerType = null, $diskOptions = [])\n    {\n        $writerType = FileTypeDetector::detectStrict($filePath, $writerType);\n\n        return $this->queuedWriter->store(\n            $export,\n            $filePath,\n            $disk,\n            $writerType,\n            $diskOptions\n        );\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function raw($export, string $writerType)\n    {\n        $temporaryFile = $this->writer->export($export, $writerType);\n\n        $contents = $temporaryFile->contents();\n        $temporaryFile->delete();\n\n        return $contents;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function import($import, $filePath, ?string $disk = null, ?string $readerType = null)\n    {\n        $readerType = FileTypeDetector::detect($filePath, $readerType);\n        $response   = $this->reader->read($import, $filePath, $readerType, $disk);\n\n        if ($response instanceof PendingDispatch) {\n            return $response;\n        }\n\n        return $this;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function toArray($import, $filePath, ?string $disk = null, ?string $readerType = null): array\n    {\n        $readerType = FileTypeDetector::detect($filePath, $readerType);\n\n        return $this->reader->toArray($import, $filePath, $readerType, $disk);\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function toCollection($import, $filePath, ?string $disk = null, ?string $readerType = null): Collection\n    {\n        $readerType = FileTypeDetector::detect($filePath, $readerType);\n\n        return $this->reader->toCollection($import, $filePath, $readerType, $disk);\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function queueImport(ShouldQueue $import, $filePath, ?string $disk = null, ?string $readerType = null)\n    {\n        return $this->import($import, $filePath, $disk, $readerType);\n    }\n\n    /**\n     * @param  object  $export\n     * @param  string|null  $fileName\n     * @param  string  $writerType\n     * @return TemporaryFile\n     *\n     * @throws \\PhpOffice\\PhpSpreadsheet\\Exception\n     */\n    protected function export($export, string $fileName, ?string $writerType = null): TemporaryFile\n    {\n        $writerType = FileTypeDetector::detectStrict($fileName, $writerType);\n\n        return $this->writer->export($export, $writerType);\n    }\n}\n"
  },
  {
    "path": "src/ExcelServiceProvider.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel;\n\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Support\\Collection;\nuse Illuminate\\Support\\ServiceProvider;\nuse Laravel\\Lumen\\Application as LumenApplication;\nuse Maatwebsite\\Excel\\Cache\\CacheManager;\nuse Maatwebsite\\Excel\\Console\\ExportMakeCommand;\nuse Maatwebsite\\Excel\\Console\\ImportMakeCommand;\nuse Maatwebsite\\Excel\\Files\\Filesystem;\nuse Maatwebsite\\Excel\\Files\\TemporaryFileFactory;\nuse Maatwebsite\\Excel\\Mixins\\DownloadCollectionMixin;\nuse Maatwebsite\\Excel\\Mixins\\DownloadQueryMacro;\nuse Maatwebsite\\Excel\\Mixins\\ImportAsMacro;\nuse Maatwebsite\\Excel\\Mixins\\ImportMacro;\nuse Maatwebsite\\Excel\\Mixins\\StoreCollectionMixin;\nuse Maatwebsite\\Excel\\Mixins\\StoreQueryMacro;\nuse Maatwebsite\\Excel\\Transactions\\TransactionHandler;\nuse Maatwebsite\\Excel\\Transactions\\TransactionManager;\n\nclass ExcelServiceProvider extends ServiceProvider\n{\n    /**\n     * {@inheritdoc}\n     */\n    public function boot()\n    {\n        if ($this->app->runningInConsole()) {\n            $this->publishes([\n                __DIR__ . '/Console/stubs/export.model.stub'       => base_path('stubs/export.model.stub'),\n                __DIR__ . '/Console/stubs/export.plain.stub'       => base_path('stubs/export.plain.stub'),\n                __DIR__ . '/Console/stubs/export.query.stub'       => base_path('stubs/export.query.stub'),\n                __DIR__ . '/Console/stubs/export.query-model.stub' => base_path('stubs/export.query-model.stub'),\n                __DIR__ . '/Console/stubs/import.collection.stub'  => base_path('stubs/import.collection.stub'),\n                __DIR__ . '/Console/stubs/import.model.stub'       => base_path('stubs/import.model.stub'),\n            ], 'stubs');\n\n            if ($this->app instanceof LumenApplication) {\n                $this->app->configure('excel');\n            } else {\n                $this->publishes([\n                    $this->getConfigFile() => config_path('excel.php'),\n                ], 'config');\n            }\n        }\n\n        if ($this->app instanceof \\Illuminate\\Foundation\\Application) {\n            // Laravel\n            $this->app->booted(function ($app) {\n                $app->make(SettingsProvider::class)->provide();\n            });\n        } else {\n            // Lumen\n            $this->app->make(SettingsProvider::class)->provide();\n        }\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function register()\n    {\n        $this->mergeConfigFrom(\n            $this->getConfigFile(),\n            'excel'\n        );\n\n        $this->app->bind(CacheManager::class, function ($app) {\n            return new CacheManager($app);\n        });\n\n        $this->app->singleton(TransactionManager::class, function ($app) {\n            return new TransactionManager($app);\n        });\n\n        $this->app->bind(TransactionHandler::class, function ($app) {\n            return $app->make(TransactionManager::class)->driver();\n        });\n\n        $this->app->bind(TemporaryFileFactory::class, function () {\n            return new TemporaryFileFactory(\n                config('excel.temporary_files.local_path', config('excel.exports.temp_path', storage_path('framework/laravel-excel'))),\n                config('excel.temporary_files.remote_disk')\n            );\n        });\n\n        $this->app->bind(Filesystem::class, function ($app) {\n            return new Filesystem($app->make('filesystem'));\n        });\n\n        $this->app->bind('excel', function ($app) {\n            return new Excel(\n                $app->make(Writer::class),\n                $app->make(QueuedWriter::class),\n                $app->make(Reader::class),\n                $app->make(Filesystem::class)\n            );\n        });\n\n        $this->app->alias('excel', Excel::class);\n        $this->app->alias('excel', Exporter::class);\n        $this->app->alias('excel', Importer::class);\n\n        Collection::mixin(new DownloadCollectionMixin);\n        Collection::mixin(new StoreCollectionMixin);\n        Builder::macro('downloadExcel', (new DownloadQueryMacro)());\n        Builder::macro('storeExcel', (new StoreQueryMacro())());\n        Builder::macro('import', (new ImportMacro())());\n        Builder::macro('importAs', (new ImportAsMacro())());\n\n        $this->commands([\n            ExportMakeCommand::class,\n            ImportMakeCommand::class,\n        ]);\n    }\n\n    /**\n     * @return string\n     */\n    protected function getConfigFile(): string\n    {\n        return __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'excel.php';\n    }\n}\n"
  },
  {
    "path": "src/Exceptions/ConcernConflictException.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Exceptions;\n\nuse LogicException;\n\nclass ConcernConflictException extends LogicException implements LaravelExcelException\n{\n    /**\n     * @return ConcernConflictException\n     */\n    public static function queryOrCollectionAndView()\n    {\n        return new static('Cannot use FromQuery, FromArray or FromCollection and FromView on the same sheet.');\n    }\n}\n"
  },
  {
    "path": "src/Exceptions/LaravelExcelException.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Exceptions;\n\nuse Throwable;\n\ninterface LaravelExcelException extends Throwable\n{\n}\n"
  },
  {
    "path": "src/Exceptions/NoFilePathGivenException.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Exceptions;\n\nuse InvalidArgumentException;\nuse Throwable;\n\nclass NoFilePathGivenException extends InvalidArgumentException implements LaravelExcelException\n{\n    /**\n     * @param  string  $message\n     * @param  int  $code\n     * @param  Throwable|null  $previous\n     */\n    public function __construct(\n        $message = 'A filepath needs to be passed.',\n        $code = 0,\n        ?Throwable $previous = null\n    ) {\n        parent::__construct($message, $code, $previous);\n    }\n\n    /**\n     * @return NoFilePathGivenException\n     */\n    public static function import()\n    {\n        return new static('A filepath or UploadedFile needs to be passed to start the import.');\n    }\n\n    /**\n     * @return NoFilePathGivenException\n     */\n    public static function export()\n    {\n        return new static('A filepath needs to be passed in order to store the export.');\n    }\n}\n"
  },
  {
    "path": "src/Exceptions/NoFilenameGivenException.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Exceptions;\n\nuse InvalidArgumentException;\nuse Throwable;\n\nclass NoFilenameGivenException extends InvalidArgumentException implements LaravelExcelException\n{\n    /**\n     * @param  string  $message\n     * @param  int  $code\n     * @param  Throwable|null  $previous\n     */\n    public function __construct(\n        $message = 'A filename needs to be passed in order to download the export',\n        $code = 0,\n        ?Throwable $previous = null\n    ) {\n        parent::__construct($message, $code, $previous);\n    }\n}\n"
  },
  {
    "path": "src/Exceptions/NoSheetsFoundException.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Exceptions;\n\nuse LogicException;\n\nclass NoSheetsFoundException extends LogicException implements LaravelExcelException\n{\n}\n"
  },
  {
    "path": "src/Exceptions/NoTypeDetectedException.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Exceptions;\n\nuse Exception;\nuse Throwable;\n\nclass NoTypeDetectedException extends Exception implements LaravelExcelException\n{\n    /**\n     * @param  string  $message\n     * @param  int  $code\n     * @param  Throwable|null  $previous\n     */\n    public function __construct(\n        $message = 'No ReaderType or WriterType could be detected. Make sure you either pass a valid extension to the filename or pass an explicit type.',\n        $code = 0,\n        ?Throwable $previous = null\n    ) {\n        parent::__construct($message, $code, $previous);\n    }\n}\n"
  },
  {
    "path": "src/Exceptions/RowSkippedException.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Exceptions;\n\nuse Exception;\nuse Illuminate\\Support\\Collection;\nuse Maatwebsite\\Excel\\Validators\\Failure;\n\nclass RowSkippedException extends Exception\n{\n    /**\n     * @var Failure[]\n     */\n    private $failures;\n\n    /**\n     * @param  Failure  ...$failures\n     */\n    public function __construct(Failure ...$failures)\n    {\n        $this->failures = $failures;\n\n        parent::__construct();\n    }\n\n    /**\n     * @return Failure[]|Collection\n     */\n    public function failures(): Collection\n    {\n        return new Collection($this->failures);\n    }\n\n    /**\n     * @return int[]\n     */\n    public function skippedRows(): array\n    {\n        return $this->failures()->map->row()->all();\n    }\n}\n"
  },
  {
    "path": "src/Exceptions/SheetNotFoundException.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Exceptions;\n\nclass SheetNotFoundException extends \\Exception implements LaravelExcelException\n{\n    /**\n     * @param  string  $name\n     * @return SheetNotFoundException\n     */\n    public static function byName(string $name): SheetNotFoundException\n    {\n        return new static(\"Your requested sheet name [{$name}] is out of bounds.\");\n    }\n\n    /**\n     * @param  int  $index\n     * @param  int  $sheetCount\n     * @return SheetNotFoundException\n     */\n    public static function byIndex(int $index, int $sheetCount): SheetNotFoundException\n    {\n        return new static(\"Your requested sheet index: {$index} is out of bounds. The actual number of sheets is {$sheetCount}.\");\n    }\n}\n"
  },
  {
    "path": "src/Exceptions/UnreadableFileException.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Exceptions;\n\nuse Exception;\nuse Throwable;\n\nclass UnreadableFileException extends Exception implements LaravelExcelException\n{\n    /**\n     * @param  string  $message\n     * @param  int  $code\n     * @param  Throwable|null  $previous\n     */\n    public function __construct(\n        $message = 'File could not be read',\n        $code = 0,\n        ?Throwable $previous = null\n    ) {\n        parent::__construct($message, $code, $previous);\n    }\n}\n"
  },
  {
    "path": "src/Exporter.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel;\n\ninterface Exporter\n{\n    /**\n     * @param  object  $export\n     * @param  string|null  $fileName\n     * @param  string  $writerType\n     * @param  array  $headers\n     * @return \\Symfony\\Component\\HttpFoundation\\BinaryFileResponse\n     *\n     * @throws \\PhpOffice\\PhpSpreadsheet\\Exception\n     * @throws \\PhpOffice\\PhpSpreadsheet\\Writer\\Exception\n     */\n    public function download($export, string $fileName, ?string $writerType = null, array $headers = []);\n\n    /**\n     * @param  object  $export\n     * @param  string  $filePath\n     * @param  string|null  $diskName\n     * @param  string  $writerType\n     * @param  mixed  $diskOptions\n     * @return bool\n     *\n     * @throws \\PhpOffice\\PhpSpreadsheet\\Exception\n     * @throws \\PhpOffice\\PhpSpreadsheet\\Writer\\Exception\n     */\n    public function store($export, string $filePath, ?string $diskName = null, ?string $writerType = null, $diskOptions = []);\n\n    /**\n     * @param  object  $export\n     * @param  string  $filePath\n     * @param  string|null  $disk\n     * @param  string  $writerType\n     * @param  mixed  $diskOptions\n     * @return \\Illuminate\\Foundation\\Bus\\PendingDispatch\n     */\n    public function queue($export, string $filePath, ?string $disk = null, ?string $writerType = null, $diskOptions = []);\n\n    /**\n     * @param  object  $export\n     * @param  string  $writerType\n     * @return string\n     */\n    public function raw($export, string $writerType);\n}\n"
  },
  {
    "path": "src/Facades/Excel.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Facades;\n\nuse Illuminate\\Foundation\\Bus\\PendingDispatch;\nuse Illuminate\\Http\\UploadedFile;\nuse Illuminate\\Support\\Collection;\nuse Illuminate\\Support\\Facades\\Facade;\nuse Maatwebsite\\Excel\\Excel as BaseExcel;\nuse Maatwebsite\\Excel\\Fakes\\ExcelFake;\nuse Symfony\\Component\\HttpFoundation\\BinaryFileResponse;\n\n/**\n * @method static BinaryFileResponse download(object $export, string $fileName, string $writerType = null, array $headers = [])\n * @method static bool store(object $export, string $filePath, string $disk = null, string $writerType = null, $diskOptions = [])\n * @method static PendingDispatch queue(object $export, string $filePath, string $disk = null, string $writerType = null, $diskOptions = [])\n * @method static string raw(object $export, string $writerType)\n * @method static BaseExcel import(object $import, string|UploadedFile $filePath, string $disk = null, string $readerType = null)\n * @method static array toArray(object $import, string|UploadedFile $filePath, string $disk = null, string $readerType = null)\n * @method static Collection toCollection(object $import, string|UploadedFile $filePath, string $disk = null, string $readerType = null)\n * @method static PendingDispatch queueImport(object $import, string|UploadedFile $filePath, string $disk = null, string $readerType = null)\n * @method static void matchByRegex()\n * @method static void doNotMatchByRegex()\n * @method static void assertDownloaded(string $fileName, callable $callback = null)\n * @method static void assertStored(string $filePath, string|callable $disk = null, callable $callback = null)\n * @method static void assertQueued(string $filePath, string|callable $disk = null, callable $callback = null)\n * @method static void assertQueuedWithChain(array $chain)\n * @method static void assertExportedInRaw(string $classname, callable $callback = null)\n * @method static void assertImported(string $filePath, string|callable $disk = null, callable $callback = null)\n */\nclass Excel extends Facade\n{\n    /**\n     * Replace the bound instance with a fake.\n     *\n     * @return void\n     */\n    public static function fake()\n    {\n        static::swap(new ExcelFake());\n    }\n\n    /**\n     * Get the registered name of the component.\n     *\n     * @return string\n     */\n    protected static function getFacadeAccessor()\n    {\n        return 'excel';\n    }\n}\n"
  },
  {
    "path": "src/Factories/ReaderFactory.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Factories;\n\nuse Maatwebsite\\Excel\\Concerns\\MapsCsvSettings;\nuse Maatwebsite\\Excel\\Concerns\\WithCustomCsvSettings;\nuse Maatwebsite\\Excel\\Concerns\\WithLimit;\nuse Maatwebsite\\Excel\\Concerns\\WithReadFilter;\nuse Maatwebsite\\Excel\\Concerns\\WithStartRow;\nuse Maatwebsite\\Excel\\Exceptions\\NoTypeDetectedException;\nuse Maatwebsite\\Excel\\Files\\TemporaryFile;\nuse Maatwebsite\\Excel\\Filters\\LimitFilter;\nuse PhpOffice\\PhpSpreadsheet\\IOFactory;\nuse PhpOffice\\PhpSpreadsheet\\Reader\\Csv;\nuse PhpOffice\\PhpSpreadsheet\\Reader\\Exception;\nuse PhpOffice\\PhpSpreadsheet\\Reader\\IReader;\n\nclass ReaderFactory\n{\n    use MapsCsvSettings;\n\n    /**\n     * @param  object  $import\n     * @param  TemporaryFile  $file\n     * @param  string  $readerType\n     * @return IReader\n     *\n     * @throws Exception\n     */\n    public static function make($import, TemporaryFile $file, ?string $readerType = null): IReader\n    {\n        $reader = IOFactory::createReader(\n            $readerType ?: static::identify($file)\n        );\n\n        if (method_exists($reader, 'setReadDataOnly')) {\n            $reader->setReadDataOnly(config('excel.imports.read_only', true));\n        }\n\n        if (method_exists($reader, 'setReadEmptyCells')) {\n            $reader->setReadEmptyCells(!config('excel.imports.ignore_empty', false));\n        }\n\n        if ($reader instanceof Csv) {\n            static::applyCsvSettings(config('excel.imports.csv', []));\n\n            if ($import instanceof WithCustomCsvSettings) {\n                static::applyCsvSettings($import->getCsvSettings());\n            }\n\n            $reader->setDelimiter(static::$delimiter);\n            $reader->setEnclosure(static::$enclosure);\n            $reader->setEscapeCharacter(static::$escapeCharacter);\n            $reader->setContiguous(static::$contiguous);\n            $reader->setInputEncoding(static::$inputEncoding);\n            if (method_exists($reader, 'setTestAutoDetect')) {\n                $reader->setTestAutoDetect(static::$testAutoDetect);\n            }\n        }\n\n        if ($import instanceof WithReadFilter) {\n            $reader->setReadFilter($import->readFilter());\n        } elseif ($import instanceof WithLimit) {\n            $reader->setReadFilter(new LimitFilter(\n                $import instanceof WithStartRow ? $import->startRow() : 1,\n                $import->limit()\n            ));\n        }\n\n        return $reader;\n    }\n\n    /**\n     * @param  TemporaryFile  $temporaryFile\n     * @return string\n     *\n     * @throws NoTypeDetectedException\n     */\n    private static function identify(TemporaryFile $temporaryFile): string\n    {\n        try {\n            return IOFactory::identify($temporaryFile->getLocalPath());\n        } catch (Exception $e) {\n            throw new NoTypeDetectedException('', 0, $e);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Factories/WriterFactory.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Factories;\n\nuse Maatwebsite\\Excel\\Cache\\CacheManager;\nuse Maatwebsite\\Excel\\Concerns\\MapsCsvSettings;\nuse Maatwebsite\\Excel\\Concerns\\WithCharts;\nuse Maatwebsite\\Excel\\Concerns\\WithCustomCsvSettings;\nuse Maatwebsite\\Excel\\Concerns\\WithMultipleSheets;\nuse Maatwebsite\\Excel\\Concerns\\WithPreCalculateFormulas;\nuse PhpOffice\\PhpSpreadsheet\\IOFactory;\nuse PhpOffice\\PhpSpreadsheet\\Spreadsheet;\nuse PhpOffice\\PhpSpreadsheet\\Writer\\Csv;\nuse PhpOffice\\PhpSpreadsheet\\Writer\\Html;\nuse PhpOffice\\PhpSpreadsheet\\Writer\\IWriter;\n\nclass WriterFactory\n{\n    use MapsCsvSettings;\n\n    /**\n     * @param  string  $writerType\n     * @param  Spreadsheet  $spreadsheet\n     * @param  object  $export\n     * @param  string|null  $filePath\n     * @return IWriter\n     *\n     * @throws \\PhpOffice\\PhpSpreadsheet\\Writer\\Exception\n     */\n    public static function make(string $writerType, Spreadsheet $spreadsheet, $export, ?string $filePath = null): IWriter\n    {\n        $writer = IOFactory::createWriter($spreadsheet, $writerType);\n\n        $writer->setUseDiskCaching(\n            config('excel.cache.driver', CacheManager::DRIVER_MEMORY) !== CacheManager::DRIVER_MEMORY\n        );\n\n        if (static::includesCharts($export)) {\n            $writer->setIncludeCharts(true);\n        }\n\n        if ($writer instanceof Html && $export instanceof WithMultipleSheets) {\n            $writer->writeAllSheets();\n        }\n\n        if ($writer instanceof Csv) {\n            static::applyCsvSettings(config('excel.exports.csv', []));\n\n            // Auto-detect TSV files and apply tab delimiter\n            if ($filePath && static::isTsvFile($filePath) && !($export instanceof WithCustomCsvSettings)) {\n                static::applyCsvSettings(['delimiter' => \"\\t\"]);\n            }\n\n            if ($export instanceof WithCustomCsvSettings) {\n                static::applyCsvSettings($export->getCsvSettings());\n            }\n\n            $writer->setDelimiter(static::$delimiter);\n            $writer->setEnclosure(static::$enclosure);\n            $writer->setEnclosureRequired((bool) static::$enclosure);\n            $writer->setLineEnding(static::$lineEnding);\n            $writer->setUseBOM(static::$useBom);\n            $writer->setIncludeSeparatorLine(static::$includeSeparatorLine);\n            $writer->setExcelCompatibility(static::$excelCompatibility);\n            $writer->setOutputEncoding(static::$outputEncoding);\n        }\n\n        // Calculation settings\n        $writer->setPreCalculateFormulas(\n            $export instanceof WithPreCalculateFormulas\n                ? true\n                : config('excel.exports.pre_calculate_formulas', false)\n        );\n\n        return $writer;\n    }\n\n    /**\n     * @param  $export\n     * @return bool\n     */\n    private static function includesCharts($export): bool\n    {\n        if ($export instanceof WithCharts) {\n            return true;\n        }\n\n        if ($export instanceof WithMultipleSheets) {\n            foreach ($export->sheets() as $sheet) {\n                if ($sheet instanceof WithCharts) {\n                    return true;\n                }\n            }\n        }\n\n        return false;\n    }\n\n    /**\n     * @param  string  $filePath\n     * @return bool\n     */\n    private static function isTsvFile(string $filePath): bool\n    {\n        $pathInfo  = pathinfo($filePath);\n        $extension = strtolower($pathInfo['extension'] ?? '');\n\n        return $extension === 'tsv';\n    }\n}\n"
  },
  {
    "path": "src/Fakes/ExcelFake.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Fakes;\n\nuse Illuminate\\Bus\\Queueable;\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Illuminate\\Foundation\\Bus\\PendingDispatch;\nuse Illuminate\\Support\\Collection;\nuse Illuminate\\Support\\Facades\\Queue;\nuse Illuminate\\Support\\Traits\\Macroable;\nuse Maatwebsite\\Excel\\Exporter;\nuse Maatwebsite\\Excel\\Importer;\nuse Maatwebsite\\Excel\\Reader;\nuse PHPUnit\\Framework\\Assert;\nuse Symfony\\Component\\HttpFoundation\\BinaryFileResponse;\nuse Symfony\\Component\\HttpFoundation\\File\\UploadedFile;\n\nclass ExcelFake implements Exporter, Importer\n{\n    use Macroable;\n\n    /**\n     * @var array\n     */\n    protected $downloads = [];\n\n    /**\n     * @var array\n     */\n    protected $stored = [];\n\n    /**\n     * @var array\n     */\n    protected $queued = [];\n\n    /**\n     * @var array\n     */\n    protected $raws = [];\n\n    /**\n     * @var array\n     */\n    protected $imported = [];\n\n    /**\n     * @var bool\n     */\n    protected $matchByRegex = false;\n\n    /**\n     * @var object|null\n     */\n    protected $job;\n\n    /**\n     * {@inheritdoc}\n     */\n    public function download($export, string $fileName, ?string $writerType = null, array $headers = [])\n    {\n        $this->downloads[$fileName] = $export;\n\n        return new BinaryFileResponse(__DIR__ . '/fake_file');\n    }\n\n    /**\n     * {@inheritdoc}\n     *\n     * @param  string|null  $diskName  Fallback for usage with named properties\n     */\n    public function store($export, string $filePath, ?string $disk = null, ?string $writerType = null, $diskOptions = [], ?string $diskName = null)\n    {\n        if ($export instanceof ShouldQueue) {\n            return $this->queue($export, $filePath, $disk ?: $diskName, $writerType);\n        }\n\n        $this->stored[$disk ?: $diskName ?: 'default'][$filePath] = $export;\n\n        return true;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function queue($export, string $filePath, ?string $disk = null, ?string $writerType = null, $diskOptions = [])\n    {\n        Queue::fake();\n\n        $this->stored[$disk ?? 'default'][$filePath] = $export;\n        $this->queued[$disk ?? 'default'][$filePath] = $export;\n\n        $this->job = new class\n        {\n            use Queueable;\n\n            public function handle()\n            {\n                //\n            }\n        };\n\n        Queue::push($this->job);\n\n        return new PendingDispatch($this->job);\n    }\n\n    /**\n     * @param  object  $export\n     * @param  string  $writerType\n     * @return string\n     */\n    public function raw($export, string $writerType)\n    {\n        $this->raws[get_class($export)] = $export;\n\n        return 'RAW-CONTENTS';\n    }\n\n    /**\n     * @param  object  $import\n     * @param  string|UploadedFile  $file\n     * @param  string|null  $disk\n     * @param  string|null  $readerType\n     * @return Reader|PendingDispatch\n     */\n    public function import($import, $file, ?string $disk = null, ?string $readerType = null)\n    {\n        if ($import instanceof ShouldQueue) {\n            return $this->queueImport($import, $file, $disk, $readerType);\n        }\n\n        $filePath = ($file instanceof UploadedFile) ? $file->getClientOriginalName() : $file;\n\n        $this->imported[$disk ?? 'default'][$filePath] = $import;\n\n        return $this;\n    }\n\n    /**\n     * @param  object  $import\n     * @param  string|UploadedFile  $file\n     * @param  string|null  $disk\n     * @param  string|null  $readerType\n     * @return array\n     */\n    public function toArray($import, $file, ?string $disk = null, ?string $readerType = null): array\n    {\n        $filePath = ($file instanceof UploadedFile) ? $file->getFilename() : $file;\n\n        $this->imported[$disk ?? 'default'][$filePath] = $import;\n\n        return [];\n    }\n\n    /**\n     * @param  object  $import\n     * @param  string|UploadedFile  $file\n     * @param  string|null  $disk\n     * @param  string|null  $readerType\n     * @return Collection\n     */\n    public function toCollection($import, $file, ?string $disk = null, ?string $readerType = null): Collection\n    {\n        $filePath = ($file instanceof UploadedFile) ? $file->getFilename() : $file;\n\n        $this->imported[$disk ?? 'default'][$filePath] = $import;\n\n        return new Collection();\n    }\n\n    /**\n     * @param  ShouldQueue  $import\n     * @param  string|UploadedFile  $file\n     * @param  string|null  $disk\n     * @param  string  $readerType\n     * @return PendingDispatch\n     */\n    public function queueImport(ShouldQueue $import, $file, ?string $disk = null, ?string $readerType = null)\n    {\n        Queue::fake();\n\n        $filePath = ($file instanceof UploadedFile) ? $file->getFilename() : $file;\n\n        $this->queued[$disk ?? 'default'][$filePath]   = $import;\n        $this->imported[$disk ?? 'default'][$filePath] = $import;\n\n        $this->job = new class\n        {\n            use Queueable;\n\n            public function handle()\n            {\n                //\n            }\n        };\n\n        Queue::push($this->job);\n\n        return new PendingDispatch($this->job);\n    }\n\n    /**\n     * When asserting downloaded, stored, queued or imported, use regular expression\n     * to look for a matching file path.\n     *\n     * @return void\n     */\n    public function matchByRegex()\n    {\n        $this->matchByRegex = true;\n    }\n\n    /**\n     * When asserting downloaded, stored, queued or imported, use regular string\n     * comparison for matching file path.\n     *\n     * @return void\n     */\n    public function doNotMatchByRegex()\n    {\n        $this->matchByRegex = false;\n    }\n\n    /**\n     * @param  string  $fileName\n     * @param  callable|null  $callback\n     */\n    public function assertDownloaded(string $fileName, $callback = null)\n    {\n        $fileName = $this->assertArrayHasKey($fileName, $this->downloads, sprintf('%s is not downloaded', $fileName));\n\n        $callback = $callback ?: function () {\n            return true;\n        };\n\n        Assert::assertTrue(\n            $callback($this->downloads[$fileName]),\n            \"The file [{$fileName}] was not downloaded with the expected data.\"\n        );\n    }\n\n    /**\n     * @param  string  $filePath\n     * @param  string|callable|null  $disk\n     * @param  callable|null  $callback\n     */\n    public function assertStored(string $filePath, $disk = null, $callback = null)\n    {\n        if (is_callable($disk)) {\n            $callback = $disk;\n            $disk     = null;\n        }\n\n        $disk         = $disk ?? 'default';\n        $storedOnDisk = $this->stored[$disk] ?? [];\n\n        $filePath = $this->assertArrayHasKey(\n            $filePath,\n            $storedOnDisk,\n            sprintf('%s is not stored on disk %s', $filePath, $disk)\n        );\n\n        $callback = $callback ?: function () {\n            return true;\n        };\n\n        Assert::assertTrue(\n            $callback($storedOnDisk[$filePath]),\n            \"The file [{$filePath}] was not stored with the expected data.\"\n        );\n    }\n\n    /**\n     * @param  string  $filePath\n     * @param  string|callable|null  $disk\n     * @param  callable|null  $callback\n     */\n    public function assertQueued(string $filePath, $disk = null, $callback = null)\n    {\n        if (is_callable($disk)) {\n            $callback = $disk;\n            $disk     = null;\n        }\n\n        $disk          = $disk ?? 'default';\n        $queuedForDisk = $this->queued[$disk] ?? [];\n\n        $filePath = $this->assertArrayHasKey(\n            $filePath,\n            $queuedForDisk,\n            sprintf('%s is not queued for export on disk %s', $filePath, $disk)\n        );\n\n        $callback = $callback ?: function () {\n            return true;\n        };\n\n        Assert::assertTrue(\n            $callback($queuedForDisk[$filePath]),\n            \"The file [{$filePath}] was not stored with the expected data.\"\n        );\n    }\n\n    public function assertQueuedWithChain($chain): void\n    {\n        Queue::assertPushedWithChain(get_class($this->job), $chain);\n    }\n\n    /**\n     * @param  string  $classname\n     * @param  callable|null  $callback\n     */\n    public function assertExportedInRaw(string $classname, $callback = null)\n    {\n        Assert::assertArrayHasKey($classname, $this->raws, sprintf('%s is not exported in raw', $classname));\n\n        $callback = $callback ?: function () {\n            return true;\n        };\n\n        Assert::assertTrue(\n            $callback($this->raws[$classname]),\n            \"The [{$classname}] export was not exported in raw with the expected data.\"\n        );\n    }\n\n    /**\n     * @param  string  $filePath\n     * @param  string|callable|null  $disk\n     * @param  callable|null  $callback\n     */\n    public function assertImported(string $filePath, $disk = null, $callback = null)\n    {\n        if (is_callable($disk)) {\n            $callback = $disk;\n            $disk     = null;\n        }\n\n        $disk           = $disk ?? 'default';\n        $importedOnDisk = $this->imported[$disk] ?? [];\n\n        $filePath = $this->assertArrayHasKey(\n            $filePath,\n            $importedOnDisk,\n            sprintf('%s is not stored on disk %s', $filePath, $disk)\n        );\n\n        $callback = $callback ?: function () {\n            return true;\n        };\n\n        Assert::assertTrue(\n            $callback($importedOnDisk[$filePath]),\n            \"The file [{$filePath}] was not imported with the expected data.\"\n        );\n    }\n\n    /**\n     * Asserts that an array has a specified key and returns the key if successful.\n     *\n     * @see matchByRegex for more information about file path matching\n     *\n     * @param  string  $key\n     * @param  array  $array\n     * @param  string  $message\n     * @return string\n     *\n     * @throws ExpectationFailedException\n     * @throws \\SebastianBergmann\\RecursionContext\\InvalidArgumentException\n     * @throws Exception\n     */\n    protected function assertArrayHasKey(string $key, array $disk, string $message = ''): string\n    {\n        if ($this->matchByRegex) {\n            $files   = array_keys($disk);\n            $results = preg_grep($key, $files);\n            Assert::assertGreaterThan(0, count($results), $message);\n            Assert::assertEquals(1, count($results), \"More than one result matches the file name expression '$key'.\");\n\n            return array_values($results)[0];\n        }\n        Assert::assertArrayHasKey($key, $disk, $message);\n\n        return $key;\n    }\n}\n"
  },
  {
    "path": "src/Fakes/fake_file",
    "content": ""
  },
  {
    "path": "src/Files/Disk.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Files;\n\nuse Illuminate\\Contracts\\Filesystem\\Filesystem as IlluminateFilesystem;\n\n/**\n * @method bool get(string $filename)\n * @method resource readStream(string $filename)\n * @method bool delete(string $filename)\n * @method bool exists(string $filename)\n */\nclass Disk\n{\n    /**\n     * @var IlluminateFilesystem\n     */\n    protected $disk;\n\n    /**\n     * @var string|null\n     */\n    protected $name;\n\n    /**\n     * @var array\n     */\n    protected $diskOptions;\n\n    /**\n     * @param  IlluminateFilesystem  $disk\n     * @param  string|null  $name\n     * @param  array  $diskOptions\n     */\n    public function __construct(IlluminateFilesystem $disk, ?string $name = null, array $diskOptions = [])\n    {\n        $this->disk        = $disk;\n        $this->name        = $name;\n        $this->diskOptions = $diskOptions;\n    }\n\n    /**\n     * @param  string  $name\n     * @param  array  $arguments\n     * @return mixed\n     */\n    public function __call($name, $arguments)\n    {\n        return $this->disk->{$name}(...$arguments);\n    }\n\n    /**\n     * @param  string  $destination\n     * @param  string|resource  $contents\n     * @return bool\n     */\n    public function put(string $destination, $contents): bool\n    {\n        return $this->disk->put($destination, $contents, $this->diskOptions);\n    }\n\n    /**\n     * @param  TemporaryFile  $source\n     * @param  string  $destination\n     * @return bool\n     */\n    public function copy(TemporaryFile $source, string $destination): bool\n    {\n        $readStream = $source->readStream();\n\n        if (!is_resource($readStream)) {\n            return false;\n        }\n\n        if (realpath($destination)) {\n            $tempStream = fopen($destination, 'rb+');\n            $success    = stream_copy_to_stream($readStream, $tempStream) !== false;\n\n            if (is_resource($tempStream)) {\n                fclose($tempStream);\n            }\n        } else {\n            $success = $this->put($destination, $readStream);\n        }\n\n        if (is_resource($readStream)) {\n            fclose($readStream);\n        }\n\n        return $success;\n    }\n\n    /**\n     * @param  string  $filename\n     */\n    public function touch(string $filename)\n    {\n        $this->disk->put($filename, '', $this->diskOptions);\n    }\n}\n"
  },
  {
    "path": "src/Files/Filesystem.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Files;\n\nuse Illuminate\\Contracts\\Filesystem\\Factory;\n\nclass Filesystem\n{\n    /**\n     * @var Factory\n     */\n    private $filesystem;\n\n    /**\n     * @param  Factory  $filesystem\n     */\n    public function __construct(Factory $filesystem)\n    {\n        $this->filesystem = $filesystem;\n    }\n\n    /**\n     * @param  string|null  $disk\n     * @param  array  $diskOptions\n     * @return Disk\n     */\n    public function disk(?string $disk = null, array $diskOptions = []): Disk\n    {\n        return new Disk(\n            $this->filesystem->disk($disk),\n            $disk,\n            $diskOptions\n        );\n    }\n}\n"
  },
  {
    "path": "src/Files/LocalTemporaryFile.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Files;\n\nclass LocalTemporaryFile extends TemporaryFile\n{\n    /**\n     * @var string\n     */\n    private $filePath;\n\n    /**\n     * @param  string  $filePath\n     */\n    public function __construct(string $filePath)\n    {\n        touch($filePath);\n        if (($rights = config('excel.temporary_files.local_permissions.file', null)) !== null) {\n            chmod($filePath, $rights);\n        }\n\n        $this->filePath = realpath($filePath);\n    }\n\n    /**\n     * @return string\n     */\n    public function getLocalPath(): string\n    {\n        return $this->filePath;\n    }\n\n    /**\n     * @return bool\n     */\n    public function exists(): bool\n    {\n        return file_exists($this->filePath);\n    }\n\n    /**\n     * @return bool\n     */\n    public function delete(): bool\n    {\n        if (@unlink($this->filePath) || !$this->exists()) {\n            return true;\n        }\n\n        return unlink($this->filePath);\n    }\n\n    /**\n     * @return resource\n     */\n    public function readStream()\n    {\n        return fopen($this->getLocalPath(), 'rb+');\n    }\n\n    /**\n     * @return string\n     */\n    public function contents(): string\n    {\n        return file_get_contents($this->filePath);\n    }\n\n    /**\n     * @param @param string|resource $contents\n     */\n    public function put($contents)\n    {\n        file_put_contents($this->filePath, $contents);\n    }\n}\n"
  },
  {
    "path": "src/Files/RemoteTemporaryFile.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Files;\n\nuse Illuminate\\Support\\Arr;\n\nclass RemoteTemporaryFile extends TemporaryFile\n{\n    /**\n     * @var string\n     */\n    private $disk;\n\n    /**\n     * @var Disk|null\n     */\n    private $diskInstance;\n\n    /**\n     * @var string\n     */\n    private $filename;\n\n    /**\n     * @var LocalTemporaryFile\n     */\n    private $localTemporaryFile;\n\n    /**\n     * @param  string  $disk\n     * @param  string  $filename\n     * @param  LocalTemporaryFile  $localTemporaryFile\n     */\n    public function __construct(string $disk, string $filename, LocalTemporaryFile $localTemporaryFile)\n    {\n        $this->disk               = $disk;\n        $this->filename           = $filename;\n        $this->localTemporaryFile = $localTemporaryFile;\n\n        $this->disk()->touch($filename);\n    }\n\n    public function __sleep()\n    {\n        return ['disk', 'filename', 'localTemporaryFile'];\n    }\n\n    /**\n     * @return string\n     */\n    public function getLocalPath(): string\n    {\n        return $this->localTemporaryFile->getLocalPath();\n    }\n\n    /**\n     * @return bool\n     */\n    public function existsLocally(): bool\n    {\n        return $this->localTemporaryFile->exists();\n    }\n\n    /**\n     * @return bool\n     */\n    public function exists(): bool\n    {\n        return $this->disk()->exists($this->filename);\n    }\n\n    /**\n     * @return bool\n     */\n    public function deleteLocalCopy(): bool\n    {\n        return $this->localTemporaryFile->delete();\n    }\n\n    /**\n     * @return bool\n     */\n    public function delete(): bool\n    {\n        // we don't need to delete local copy as it's deleted at end of each chunk\n        if (!config('excel.temporary_files.force_resync_remote')) {\n            $this->deleteLocalCopy();\n        }\n\n        return $this->disk()->delete($this->filename);\n    }\n\n    /**\n     * @return TemporaryFile\n     */\n    public function sync(bool $copy = true): TemporaryFile\n    {\n        if (!$this->localTemporaryFile->exists()) {\n            $this->localTemporaryFile = resolve(TemporaryFileFactory::class)\n                ->makeLocal(Arr::last(explode('/', $this->filename)));\n        }\n\n        $copy && $this->disk()->copy(\n            $this,\n            $this->localTemporaryFile->getLocalPath()\n        );\n\n        return $this;\n    }\n\n    /**\n     * Store on remote disk.\n     */\n    public function updateRemote()\n    {\n        $this->disk()->copy(\n            $this->localTemporaryFile,\n            $this->filename\n        );\n    }\n\n    /**\n     * @return resource\n     */\n    public function readStream()\n    {\n        return $this->disk()->readStream($this->filename);\n    }\n\n    /**\n     * @return string\n     */\n    public function contents(): string\n    {\n        return $this->disk()->get($this->filename);\n    }\n\n    /**\n     * @param  string|resource  $contents\n     */\n    public function put($contents)\n    {\n        $this->disk()->put($this->filename, $contents);\n    }\n\n    /**\n     * @return Disk\n     */\n    public function disk(): Disk\n    {\n        return $this->diskInstance ?: $this->diskInstance = app(Filesystem::class)->disk($this->disk);\n    }\n}\n"
  },
  {
    "path": "src/Files/TemporaryFile.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Files;\n\nuse Illuminate\\Contracts\\Filesystem\\FileNotFoundException;\nuse Symfony\\Component\\HttpFoundation\\File\\UploadedFile;\n\nabstract class TemporaryFile\n{\n    /**\n     * @return string\n     */\n    abstract public function getLocalPath(): string;\n\n    /**\n     * @return bool\n     */\n    abstract public function exists(): bool;\n\n    /**\n     * @param @param string|resource $contents\n     */\n    abstract public function put($contents);\n\n    /**\n     * @return bool\n     */\n    abstract public function delete(): bool;\n\n    /**\n     * @return resource\n     */\n    abstract public function readStream();\n\n    /**\n     * @return string\n     */\n    abstract public function contents(): string;\n\n    /**\n     * @return TemporaryFile\n     */\n    public function sync(): TemporaryFile\n    {\n        return $this;\n    }\n\n    /**\n     * @param  string|UploadedFile  $filePath\n     * @param  string|null  $disk\n     * @return TemporaryFile\n     */\n    public function copyFrom($filePath, ?string $disk = null): TemporaryFile\n    {\n        if ($filePath instanceof UploadedFile) {\n            $readStream = fopen($filePath->getRealPath(), 'rb');\n        } elseif ($disk === null && realpath($filePath) !== false) {\n            $readStream = fopen($filePath, 'rb');\n        } else {\n            $diskInstance = app('filesystem')->disk($disk);\n\n            if (!$diskInstance->exists($filePath)) {\n                $logPath = '[' . $filePath . ']';\n\n                if ($disk) {\n                    $logPath .= ' (' . $disk . ')';\n                }\n\n                throw new FileNotFoundException('File ' . $logPath . ' does not exist and can therefore not be imported.');\n            }\n\n            $readStream = $diskInstance->readStream($filePath);\n        }\n\n        $this->put($readStream);\n\n        if (is_resource($readStream)) {\n            fclose($readStream);\n        }\n\n        return $this->sync();\n    }\n}\n"
  },
  {
    "path": "src/Files/TemporaryFileFactory.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Files;\n\nuse Illuminate\\Support\\Str;\n\nclass TemporaryFileFactory\n{\n    /**\n     * @var string|null\n     */\n    private $temporaryPath;\n\n    /**\n     * @var string|null\n     */\n    private $temporaryDisk;\n\n    /**\n     * @param  string|null  $temporaryPath\n     * @param  string|null  $temporaryDisk\n     */\n    public function __construct(?string $temporaryPath = null, ?string $temporaryDisk = null)\n    {\n        $this->temporaryPath = $temporaryPath;\n        $this->temporaryDisk = $temporaryDisk;\n    }\n\n    /**\n     * @param  string|null  $fileExtension\n     * @return TemporaryFile\n     */\n    public function make(?string $fileExtension = null): TemporaryFile\n    {\n        if (null !== $this->temporaryDisk) {\n            return $this->makeRemote($fileExtension);\n        }\n\n        return $this->makeLocal(null, $fileExtension);\n    }\n\n    /**\n     * @param  string|null  $fileName\n     * @param  string|null  $fileExtension\n     * @return LocalTemporaryFile\n     */\n    public function makeLocal(?string $fileName = null, ?string $fileExtension = null): LocalTemporaryFile\n    {\n        if (!file_exists($this->temporaryPath) && !mkdir($concurrentDirectory = $this->temporaryPath, config('excel.temporary_files.local_permissions.dir', 0777), true) && !is_dir($concurrentDirectory)) {\n            throw new \\RuntimeException(sprintf('Directory \"%s\" was not created', $concurrentDirectory));\n        }\n\n        return new LocalTemporaryFile(\n            $this->temporaryPath . DIRECTORY_SEPARATOR . ($fileName ?: $this->generateFilename($fileExtension))\n        );\n    }\n\n    /**\n     * @param  string|null  $fileExtension\n     * @return RemoteTemporaryFile\n     */\n    private function makeRemote(?string $fileExtension = null): RemoteTemporaryFile\n    {\n        $filename = $this->generateFilename($fileExtension);\n\n        return new RemoteTemporaryFile(\n            $this->temporaryDisk,\n            config('excel.temporary_files.remote_prefix') . $filename,\n            $this->makeLocal($filename)\n        );\n    }\n\n    /**\n     * @param  string|null  $fileExtension\n     * @return string\n     */\n    private function generateFilename(?string $fileExtension = null): string\n    {\n        return 'laravel-excel-' . Str::random(32) . ($fileExtension ? '.' . $fileExtension : '');\n    }\n}\n"
  },
  {
    "path": "src/Filters/ChunkReadFilter.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Filters;\n\nuse PhpOffice\\PhpSpreadsheet\\Reader\\IReadFilter;\n\nclass ChunkReadFilter implements IReadFilter\n{\n    /**\n     * @var int\n     */\n    private $headingRow;\n\n    /**\n     * @var int\n     */\n    private $startRow;\n\n    /**\n     * @var int\n     */\n    private $endRow;\n\n    /**\n     * @var string\n     */\n    private $worksheetName;\n\n    /**\n     * @param  int  $headingRow\n     * @param  int  $startRow\n     * @param  int  $chunkSize\n     * @param  string  $worksheetName\n     */\n    public function __construct(int $headingRow, int $startRow, int $chunkSize, string $worksheetName)\n    {\n        $this->headingRow    = $headingRow;\n        $this->startRow      = $startRow;\n        $this->endRow        = $startRow + $chunkSize;\n        $this->worksheetName = $worksheetName;\n    }\n\n    /**\n     * @param  string  $column\n     * @param  int  $row\n     * @param  string  $worksheetName\n     * @return bool\n     */\n    public function readCell($column, $row, $worksheetName = '')\n    {\n        //  Only read the heading row, and the rows that are configured in $this->_startRow and $this->_endRow\n        return ($worksheetName === $this->worksheetName || $worksheetName === '')\n            && ($row === $this->headingRow || ($row >= $this->startRow && $row < $this->endRow));\n    }\n}\n"
  },
  {
    "path": "src/Filters/LimitFilter.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Filters;\n\nuse PhpOffice\\PhpSpreadsheet\\Reader\\IReadFilter;\n\nclass LimitFilter implements IReadFilter\n{\n    /**\n     * @var int\n     */\n    private $startRow;\n\n    /**\n     * @var int\n     */\n    private $endRow;\n\n    /**\n     * @param  int  $startRow\n     * @param  int  $limit\n     */\n    public function __construct(int $startRow, int $limit)\n    {\n        $this->startRow = $startRow;\n        $this->endRow   = $startRow + $limit;\n    }\n\n    /**\n     * @param  string  $column\n     * @param  int  $row\n     * @param  string  $worksheetName\n     * @return bool\n     */\n    public function readCell($column, $row, $worksheetName = '')\n    {\n        return $row >= $this->startRow && $row <= $this->endRow;\n    }\n}\n"
  },
  {
    "path": "src/HasEventBus.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel;\n\ntrait HasEventBus\n{\n    /**\n     * @var array\n     */\n    protected static $globalEvents = [];\n\n    /**\n     * @var array\n     */\n    protected $events = [];\n\n    /**\n     * Register local event listeners.\n     *\n     * @param  array  $listeners\n     */\n    public function registerListeners(array $listeners)\n    {\n        foreach ($listeners as $event => $listener) {\n            $this->events[$event][] = $listener;\n        }\n    }\n\n    public function clearListeners()\n    {\n        $this->events = [];\n    }\n\n    /**\n     * Register a global event listener.\n     *\n     * @param  string  $event\n     * @param  callable  $listener\n     */\n    public static function listen(string $event, callable $listener)\n    {\n        static::$globalEvents[$event][] = $listener;\n    }\n\n    /**\n     * @param  object  $event\n     */\n    public function raise($event)\n    {\n        foreach ($this->listeners($event) as $listener) {\n            $listener($event);\n        }\n    }\n\n    /**\n     * @param  object  $event\n     * @return callable[]\n     */\n    public function listeners($event): array\n    {\n        $name = \\get_class($event);\n\n        $localListeners  = $this->events[$name] ?? [];\n        $globalListeners = static::$globalEvents[$name] ?? [];\n\n        return array_merge($globalListeners, $localListeners);\n    }\n}\n"
  },
  {
    "path": "src/HeadingRowImport.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel;\n\nuse Maatwebsite\\Excel\\Concerns\\Importable;\nuse Maatwebsite\\Excel\\Concerns\\WithLimit;\nuse Maatwebsite\\Excel\\Concerns\\WithMapping;\nuse Maatwebsite\\Excel\\Concerns\\WithStartRow;\nuse Maatwebsite\\Excel\\Imports\\HeadingRowFormatter;\n\nclass HeadingRowImport implements WithStartRow, WithLimit, WithMapping\n{\n    use Importable;\n\n    /**\n     * @var int\n     */\n    private $headingRow;\n\n    /**\n     * @param  int  $headingRow\n     */\n    public function __construct(int $headingRow = 1)\n    {\n        $this->headingRow = $headingRow;\n    }\n\n    /**\n     * @return int\n     */\n    public function startRow(): int\n    {\n        return $this->headingRow;\n    }\n\n    /**\n     * @return int\n     */\n    public function limit(): int\n    {\n        return 1;\n    }\n\n    /**\n     * @param  mixed  $row\n     * @return array\n     */\n    public function map($row): array\n    {\n        return HeadingRowFormatter::format($row);\n    }\n}\n"
  },
  {
    "path": "src/Helpers/ArrayHelper.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Helpers;\n\nclass ArrayHelper\n{\n    /**\n     * @param  array  $array\n     * @return array\n     */\n    public static function ensureMultipleRows(array $array): array\n    {\n        if (static::hasMultipleRows($array)) {\n            return $array;\n        }\n\n        return [$array];\n    }\n\n    /**\n     * Only have multiple rows, if each\n     * element in the array is an array itself.\n     *\n     * @param  array  $array\n     * @return bool\n     */\n    public static function hasMultipleRows(array $array): bool\n    {\n        return count($array) === count(array_filter($array, 'is_array'));\n    }\n}\n"
  },
  {
    "path": "src/Helpers/CellHelper.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Helpers;\n\nclass CellHelper\n{\n    /**\n     * @param  string  $coordinate\n     * @return string\n     */\n    public static function getColumnFromCoordinate(string $coordinate): string\n    {\n        return preg_replace('/[0-9]/', '', $coordinate);\n    }\n}\n"
  },
  {
    "path": "src/Helpers/FileTypeDetector.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Helpers;\n\nuse Maatwebsite\\Excel\\Exceptions\\NoTypeDetectedException;\nuse Symfony\\Component\\HttpFoundation\\File\\UploadedFile;\n\nclass FileTypeDetector\n{\n    /**\n     * @param  $filePath\n     * @param  string|null  $type\n     * @return string|null\n     *\n     * @throws NoTypeDetectedException\n     */\n    public static function detect($filePath, ?string $type = null)\n    {\n        if (null !== $type) {\n            return $type;\n        }\n\n        if (!$filePath instanceof UploadedFile) {\n            $pathInfo  = pathinfo($filePath);\n            $extension = $pathInfo['extension'] ?? '';\n        } else {\n            $extension = $filePath->getClientOriginalExtension();\n        }\n\n        if (null === $type && trim($extension) === '') {\n            throw new NoTypeDetectedException();\n        }\n\n        return config('excel.extension_detector.' . strtolower($extension));\n    }\n\n    /**\n     * @param  string  $filePath\n     * @param  string|null  $type\n     * @return string\n     *\n     * @throws NoTypeDetectedException\n     */\n    public static function detectStrict(string $filePath, ?string $type = null): string\n    {\n        $type = static::detect($filePath, $type);\n\n        if (!$type) {\n            throw new NoTypeDetectedException();\n        }\n\n        return $type;\n    }\n}\n"
  },
  {
    "path": "src/Importer.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel;\n\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Illuminate\\Support\\Collection;\n\ninterface Importer\n{\n    /**\n     * @param  object  $import\n     * @param  string|\\Symfony\\Component\\HttpFoundation\\File\\UploadedFile  $filePath\n     * @param  string|null  $disk\n     * @param  string|null  $readerType\n     * @return Reader|\\Illuminate\\Foundation\\Bus\\PendingDispatch\n     */\n    public function import($import, $filePath, ?string $disk = null, ?string $readerType = null);\n\n    /**\n     * @param  object  $import\n     * @param  string|\\Symfony\\Component\\HttpFoundation\\File\\UploadedFile  $filePath\n     * @param  string|null  $disk\n     * @param  string|null  $readerType\n     * @return array\n     */\n    public function toArray($import, $filePath, ?string $disk = null, ?string $readerType = null): array;\n\n    /**\n     * @param  object  $import\n     * @param  string|\\Symfony\\Component\\HttpFoundation\\File\\UploadedFile  $filePath\n     * @param  string|null  $disk\n     * @param  string|null  $readerType\n     * @return Collection\n     */\n    public function toCollection($import, $filePath, ?string $disk = null, ?string $readerType = null): Collection;\n\n    /**\n     * @param  ShouldQueue  $import\n     * @param  string|\\Symfony\\Component\\HttpFoundation\\File\\UploadedFile  $filePath\n     * @param  string|null  $disk\n     * @param  string  $readerType\n     * @return \\Illuminate\\Foundation\\Bus\\PendingDispatch\n     */\n    public function queueImport(ShouldQueue $import, $filePath, ?string $disk = null, ?string $readerType = null);\n}\n"
  },
  {
    "path": "src/Imports/EndRowFinder.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Imports;\n\nuse Maatwebsite\\Excel\\Concerns\\WithLimit;\n\nclass EndRowFinder\n{\n    /**\n     * @param  object|WithLimit  $import\n     * @param  int  $startRow\n     * @param  int|null  $highestRow\n     * @return int|null\n     */\n    public static function find($import, ?int $startRow = null, ?int $highestRow = null)\n    {\n        if (!$import instanceof WithLimit) {\n            return null;\n        }\n\n        $limit = $import->limit();\n\n        if ($limit > $highestRow) {\n            return null;\n        }\n\n        // When no start row given,\n        // use the first row as start row.\n        $startRow = $startRow ?? 1;\n\n        // Subtract 1 row from the start row, so a limit\n        // of 1 row, will have the same start and end row.\n        return ($startRow - 1) + $limit;\n    }\n}\n"
  },
  {
    "path": "src/Imports/HeadingRowExtractor.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Imports;\n\nuse Maatwebsite\\Excel\\Concerns\\WithColumnLimit;\nuse Maatwebsite\\Excel\\Concerns\\WithGroupedHeadingRow;\nuse Maatwebsite\\Excel\\Concerns\\WithHeadingRow;\nuse Maatwebsite\\Excel\\Concerns\\WithStartRow;\nuse Maatwebsite\\Excel\\Row;\nuse PhpOffice\\PhpSpreadsheet\\Worksheet\\Worksheet;\n\nclass HeadingRowExtractor\n{\n    /**\n     * @const int\n     */\n    const DEFAULT_HEADING_ROW = 1;\n\n    /**\n     * @param  WithHeadingRow|mixed  $importable\n     * @return int\n     */\n    public static function headingRow($importable): int\n    {\n        return method_exists($importable, 'headingRow')\n            ? $importable->headingRow()\n            : self::DEFAULT_HEADING_ROW;\n    }\n\n    /**\n     * @param  WithHeadingRow|mixed  $importable\n     * @return int\n     */\n    public static function determineStartRow($importable): int\n    {\n        if ($importable instanceof WithStartRow) {\n            return $importable->startRow();\n        }\n\n        // The start row is the row after the heading row if we have one!\n        return $importable instanceof WithHeadingRow\n            ? self::headingRow($importable) + 1\n            : self::DEFAULT_HEADING_ROW;\n    }\n\n    /**\n     * @param  Worksheet  $worksheet\n     * @param  WithHeadingRow|mixed  $importable\n     * @return array\n     */\n    public static function extract(Worksheet $worksheet, $importable): array\n    {\n        if (!$importable instanceof WithHeadingRow) {\n            return [];\n        }\n\n        $headingRowNumber = self::headingRow($importable);\n        $rows             = iterator_to_array($worksheet->getRowIterator($headingRowNumber, $headingRowNumber));\n        $headingRow       = head($rows);\n        $endColumn        = $importable instanceof WithColumnLimit ? $importable->endColumn() : null;\n\n        return HeadingRowFormatter::format((new Row($headingRow))->toArray(null, false, false, $endColumn));\n    }\n\n    /**\n     * @param  array  $headingRow\n     * @param  WithGroupedHeadingRow|mixed  $importable\n     * @return array\n     */\n    public static function extractGrouping($headingRow, $importable)\n    {\n        $headerIsGrouped = array_fill(0, count($headingRow), false);\n\n        if (!$importable instanceof WithGroupedHeadingRow) {\n            return $headerIsGrouped;\n        }\n\n        array_walk($headerIsGrouped, function (&$value, $key) use ($headingRow) {\n            if (array_count_values($headingRow)[$headingRow[$key]] > 1) {\n                $value = true;\n            }\n        });\n\n        return $headerIsGrouped;\n    }\n}\n"
  },
  {
    "path": "src/Imports/HeadingRowFormatter.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Imports;\n\nuse Illuminate\\Support\\Collection;\nuse Illuminate\\Support\\Str;\nuse InvalidArgumentException;\n\nclass HeadingRowFormatter\n{\n    /**\n     * @const string\n     */\n    const FORMATTER_NONE = 'none';\n\n    /**\n     * @const string\n     */\n    const FORMATTER_SLUG = 'slug';\n\n    /**\n     * @var string\n     */\n    protected static $formatter;\n\n    /**\n     * @var callable[]\n     */\n    protected static $customFormatters = [];\n\n    /**\n     * @var array\n     */\n    protected static $defaultFormatters = [\n        self::FORMATTER_NONE,\n        self::FORMATTER_SLUG,\n    ];\n\n    /**\n     * @param  array  $headings\n     * @return array\n     */\n    public static function format(array $headings): array\n    {\n        return (new Collection($headings))->map(function ($value, $key) {\n            return static::callFormatter($value, $key);\n        })->toArray();\n    }\n\n    /**\n     * @param  string  $name\n     */\n    public static function default(?string $name = null)\n    {\n        if (null !== $name && !isset(static::$customFormatters[$name]) && !in_array($name, static::$defaultFormatters, true)) {\n            throw new InvalidArgumentException(sprintf('Formatter \"%s\" does not exist', $name));\n        }\n\n        static::$formatter = $name;\n    }\n\n    /**\n     * @param  string  $name\n     * @param  callable  $formatter\n     */\n    public static function extend(string $name, callable $formatter)\n    {\n        static::$customFormatters[$name] = $formatter;\n    }\n\n    /**\n     * Reset the formatter.\n     */\n    public static function reset()\n    {\n        static::default();\n    }\n\n    /**\n     * @param  mixed  $value\n     * @return mixed\n     */\n    protected static function callFormatter($value, $key=null)\n    {\n        static::$formatter = static::$formatter ?? config('excel.imports.heading_row.formatter', self::FORMATTER_SLUG);\n\n        // Call custom formatter\n        if (isset(static::$customFormatters[static::$formatter])) {\n            $formatter = static::$customFormatters[static::$formatter];\n\n            return $formatter($value, $key);\n        }\n\n        if (empty($value)) {\n            return $key;\n        }\n\n        if (static::$formatter === self::FORMATTER_SLUG) {\n            return Str::slug($value, '_');\n        }\n\n        // No formatter (FORMATTER_NONE)\n        return $value;\n    }\n}\n"
  },
  {
    "path": "src/Imports/ModelImporter.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Imports;\n\nuse Maatwebsite\\Excel\\Concerns\\SkipsEmptyRows;\nuse Maatwebsite\\Excel\\Concerns\\ToModel;\nuse Maatwebsite\\Excel\\Concerns\\WithBatchInserts;\nuse Maatwebsite\\Excel\\Concerns\\WithCalculatedFormulas;\nuse Maatwebsite\\Excel\\Concerns\\WithColumnLimit;\nuse Maatwebsite\\Excel\\Concerns\\WithEvents;\nuse Maatwebsite\\Excel\\Concerns\\WithFormatData;\nuse Maatwebsite\\Excel\\Concerns\\WithMapping;\nuse Maatwebsite\\Excel\\Concerns\\WithProgressBar;\nuse Maatwebsite\\Excel\\Concerns\\WithValidation;\nuse Maatwebsite\\Excel\\Events\\AfterBatch;\nuse Maatwebsite\\Excel\\HasEventBus;\nuse Maatwebsite\\Excel\\Row;\nuse PhpOffice\\PhpSpreadsheet\\Worksheet\\Worksheet;\n\nclass ModelImporter\n{\n    use HasEventBus;\n\n    /**\n     * @var ModelManager\n     */\n    private $manager;\n\n    /**\n     * @param  ModelManager  $manager\n     */\n    public function __construct(ModelManager $manager)\n    {\n        $this->manager = $manager;\n    }\n\n    /**\n     * @param  Worksheet  $worksheet\n     * @param  ToModel  $import\n     * @param  int|null  $startRow\n     * @param  string|null  $endColumn\n     *\n     * @throws \\Maatwebsite\\Excel\\Validators\\ValidationException\n     */\n    public function import(Worksheet $worksheet, ToModel $import, int $startRow = 1)\n    {\n        if ($startRow > $worksheet->getHighestRow()) {\n            return;\n        }\n        if ($import instanceof WithEvents) {\n            $this->registerListeners($import->registerEvents());\n        }\n\n        $headingRow       = HeadingRowExtractor::extract($worksheet, $import);\n        $headerIsGrouped  = HeadingRowExtractor::extractGrouping($headingRow, $import);\n        $batchSize        = $import instanceof WithBatchInserts ? $import->batchSize() : 1;\n        $endRow           = EndRowFinder::find($import, $startRow, $worksheet->getHighestRow());\n        $progessBar       = $import instanceof WithProgressBar;\n        $withMapping      = $import instanceof WithMapping;\n        $withCalcFormulas = $import instanceof WithCalculatedFormulas;\n        $formatData       = $import instanceof WithFormatData;\n        $withValidation   = $import instanceof WithValidation && method_exists($import, 'prepareForValidation');\n        $endColumn        = $import instanceof WithColumnLimit ? $import->endColumn() : null;\n\n        $this->manager->setRemembersRowNumber(method_exists($import, 'rememberRowNumber'));\n\n        $i             = 0;\n        $batchStartRow = $startRow;\n        foreach ($worksheet->getRowIterator($startRow, $endRow) as $spreadSheetRow) {\n            $i++;\n\n            $row = new Row($spreadSheetRow, $headingRow, $headerIsGrouped);\n            if (!$import instanceof SkipsEmptyRows || !$row->isEmpty($withCalcFormulas)) {\n                $rowArray = $row->toArray(null, $withCalcFormulas, $formatData, $endColumn);\n\n                if ($import instanceof SkipsEmptyRows && method_exists($import, 'isEmptyWhen') && $import->isEmptyWhen($rowArray)) {\n                    continue;\n                }\n\n                if ($withValidation) {\n                    $rowArray = $import->prepareForValidation($rowArray, $row->getIndex());\n                }\n\n                if ($withMapping) {\n                    $rowArray = $import->map($rowArray);\n                }\n\n                $this->manager->add(\n                    $row->getIndex(),\n                    $rowArray\n                );\n\n                // Flush each batch.\n                if (($i % $batchSize) === 0) {\n                    $this->flush($import, $batchSize, $batchStartRow);\n                    $batchStartRow += $i;\n                    $i = 0;\n\n                    if ($progessBar) {\n                        $import->getConsoleOutput()->progressAdvance($batchSize);\n                    }\n                }\n            }\n        }\n\n        if ($i > 0) {\n            // Flush left-overs.\n            $this->flush($import, $batchSize, $batchStartRow);\n        }\n    }\n\n    private function flush(ToModel $import, int $batchSize, int $startRow)\n    {\n        $this->manager->flush($import, $batchSize > 1);\n        $this->raise(new AfterBatch($this->manager, $import, $batchSize, $startRow));\n    }\n}\n"
  },
  {
    "path": "src/Imports/ModelManager.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Imports;\n\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Support\\Collection;\nuse Maatwebsite\\Excel\\Concerns\\PersistRelations;\nuse Maatwebsite\\Excel\\Concerns\\SkipsOnError;\nuse Maatwebsite\\Excel\\Concerns\\ToModel;\nuse Maatwebsite\\Excel\\Concerns\\WithSkipDuplicates;\nuse Maatwebsite\\Excel\\Concerns\\WithUpsertColumns;\nuse Maatwebsite\\Excel\\Concerns\\WithUpserts;\nuse Maatwebsite\\Excel\\Concerns\\WithValidation;\nuse Maatwebsite\\Excel\\Exceptions\\RowSkippedException;\nuse Maatwebsite\\Excel\\Imports\\Persistence\\CascadePersistManager;\nuse Maatwebsite\\Excel\\Validators\\RowValidator;\nuse Maatwebsite\\Excel\\Validators\\ValidationException;\nuse Throwable;\n\nclass ModelManager\n{\n    /**\n     * @var array\n     */\n    private $rows = [];\n\n    /**\n     * @var RowValidator\n     */\n    private $validator;\n    /**\n     * @var bool\n     */\n    private $remembersRowNumber = false;\n\n    /**\n     * @var CascadePersistManager\n     */\n    private $cascade;\n\n    /**\n     * @param  RowValidator  $validator\n     */\n    public function __construct(RowValidator $validator, CascadePersistManager $cascade)\n    {\n        $this->validator = $validator;\n        $this->cascade   = $cascade;\n    }\n\n    /**\n     * @param  int  $row\n     * @param  array  $attributes\n     */\n    public function add(int $row, array $attributes)\n    {\n        $this->rows[$row] = $attributes;\n    }\n\n    /**\n     * @param  bool  $remembersRowNumber\n     */\n    public function setRemembersRowNumber(bool $remembersRowNumber)\n    {\n        $this->remembersRowNumber = $remembersRowNumber;\n    }\n\n    /**\n     * @param  ToModel  $import\n     * @param  bool  $massInsert\n     *\n     * @throws ValidationException\n     */\n    public function flush(ToModel $import, bool $massInsert = false)\n    {\n        if ($import instanceof WithValidation) {\n            $this->validateRows($import);\n        }\n\n        if ($massInsert) {\n            $this->massFlush($import);\n        } else {\n            $this->singleFlush($import);\n        }\n\n        $this->rows = [];\n    }\n\n    /**\n     * @param  ToModel  $import\n     * @param  array  $attributes\n     * @param  int|null  $rowNumber\n     * @return Model[]|Collection\n     */\n    public function toModels(ToModel $import, array $attributes, $rowNumber = null): Collection\n    {\n        if ($this->remembersRowNumber) {\n            $import->rememberRowNumber($rowNumber);\n        }\n\n        return Collection::wrap($import->model($attributes));\n    }\n\n    /**\n     * @param  ToModel  $import\n     */\n    private function massFlush(ToModel $import)\n    {\n        $this->rows()\n             ->flatMap(function (array $attributes, $index) use ($import) {\n                 return $this->toModels($import, $attributes, $index);\n             })\n             ->mapToGroups(function ($model) {\n                 return [\\get_class($model) => $this->prepare($model)->getAttributes()];\n             })\n             ->each(function (Collection $models, string $model) use ($import) {\n                 try {\n                     /* @var Model $model */\n\n                     if ($import instanceof WithUpserts) {\n                         $model::query()->upsert(\n                             $models->toArray(),\n                             $import->uniqueBy(),\n                             $import instanceof WithUpsertColumns ? $import->upsertColumns() : null\n                         );\n\n                         return;\n                     } elseif ($import instanceof WithSkipDuplicates) {\n                         $model::query()->insertOrIgnore($models->toArray());\n\n                         return;\n                     }\n\n                     $model::query()->insert($models->toArray());\n                 } catch (Throwable $e) {\n                     $this->handleException($import, $e);\n                 }\n             });\n    }\n\n    /**\n     * @param  ToModel  $import\n     */\n    private function singleFlush(ToModel $import)\n    {\n        $this\n            ->rows()\n            ->each(function (array $attributes, $index) use ($import) {\n                $this->toModels($import, $attributes, $index)->each(function (Model $model) use ($import) {\n                    try {\n                        if ($import instanceof WithUpserts) {\n                            $model->upsert(\n                                $model->getAttributes(),\n                                $import->uniqueBy(),\n                                $import instanceof WithUpsertColumns ? $import->upsertColumns() : null\n                            );\n\n                            return;\n                        } elseif ($import instanceof WithSkipDuplicates) {\n                            $model::query()->insertOrIgnore([$model->getAttributes()]);\n\n                            return;\n                        }\n\n                        if ($import instanceof PersistRelations) {\n                            $this->cascade->persist($model);\n                        } else {\n                            $model->saveOrFail();\n                        }\n                    } catch (Throwable $e) {\n                        $this->handleException($import, $e);\n                    }\n                });\n            });\n    }\n\n    /**\n     * @param  Model  $model\n     * @return Model\n     */\n    private function prepare(Model $model): Model\n    {\n        if ($model->usesTimestamps()) {\n            $time = $model->freshTimestamp();\n\n            $updatedAtColumn = $model->getUpdatedAtColumn();\n\n            // If model has updated at column and not manually provided.\n            if ($updatedAtColumn && null === $model->{$updatedAtColumn}) {\n                $model->setUpdatedAt($time);\n            }\n\n            $createdAtColumn = $model->getCreatedAtColumn();\n\n            // If model has created at column and not manually provided.\n            if ($createdAtColumn && null === $model->{$createdAtColumn}) {\n                $model->setCreatedAt($time);\n            }\n        }\n\n        return $model;\n    }\n\n    /**\n     * @param  WithValidation  $import\n     *\n     * @throws ValidationException\n     */\n    private function validateRows(WithValidation $import)\n    {\n        try {\n            $this->validator->validate($this->rows, $import);\n        } catch (RowSkippedException $e) {\n            foreach ($e->skippedRows() as $row) {\n                unset($this->rows[$row]);\n            }\n        }\n    }\n\n    /**\n     * @return Collection\n     */\n    private function rows(): Collection\n    {\n        return new Collection($this->rows);\n    }\n\n    private function handleException(ToModel $import, Throwable $e): void\n    {\n        if (!$import instanceof SkipsOnError) {\n            throw $e;\n        }\n\n        $import->onError($e);\n    }\n}\n"
  },
  {
    "path": "src/Imports/Persistence/CascadePersistManager.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Imports\\Persistence;\n\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Database\\Eloquent\\Relations\\BelongsTo;\nuse Illuminate\\Database\\Eloquent\\Relations\\BelongsToMany;\nuse Illuminate\\Support\\Collection;\nuse Maatwebsite\\Excel\\Transactions\\TransactionHandler;\n\n/** @todo  */\nclass CascadePersistManager\n{\n    /**\n     * @var TransactionHandler\n     */\n    private $transaction;\n\n    /**\n     * @param  TransactionHandler  $transaction\n     */\n    public function __construct(TransactionHandler $transaction)\n    {\n        $this->transaction = $transaction;\n    }\n\n    /**\n     * @param  Model  $model\n     * @return bool\n     */\n    public function persist(Model $model): bool\n    {\n        return ($this->transaction)(function () use ($model) {\n            return $this->save($model);\n        });\n    }\n\n    /**\n     * @param  Model  $model\n     * @return bool\n     */\n    private function save(Model $model): bool\n    {\n        if (!$model->save()) {\n            return false;\n        }\n\n        foreach ($model->getRelations() as $relationName => $models) {\n            $models = array_filter(\n                $models instanceof Collection ? $models->all() : [$models]\n            );\n\n            $relation = $model->{$relationName}();\n\n            if ($relation instanceof BelongsTo) {\n                if (!$this->persistBelongsTo($relation, $models)) {\n                    return false;\n                }\n            }\n\n            if ($relation instanceof BelongsToMany) {\n                if (!$this->persistBelongsToMany($relation, $models)) {\n                    return false;\n                }\n            }\n        }\n\n        // We need to save the model again to\n        // make sure all updates are performed.\n        $model->save();\n\n        return true;\n    }\n\n    /**\n     * @param  BelongsTo  $relation\n     * @param  array  $models\n     * @return bool\n     */\n    private function persistBelongsTo(BelongsTo $relation, array $models): bool\n    {\n        // With belongs to, we first need to save all relations,\n        // so we can use their foreign key to attach to the relation.\n        foreach ($models as $model) {\n            // Cascade any relations that this child model may have.\n            if (!$this->save($model)) {\n                return false;\n            }\n\n            $relation->associate($model);\n        }\n\n        return true;\n    }\n\n    /**\n     * @param  BelongsToMany  $relation\n     * @param  array  $models\n     * @return bool\n     */\n    private function persistBelongsToMany(BelongsToMany $relation, array $models): bool\n    {\n        foreach ($models as $model) {\n            $relation->save($model);\n\n            // Cascade any relations that this child model may have.\n            if (!$this->save($model)) {\n                return false;\n            }\n        }\n\n        return true;\n    }\n}\n"
  },
  {
    "path": "src/Jobs/AfterImportJob.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Jobs;\n\nuse Illuminate\\Bus\\Queueable;\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Illuminate\\Queue\\InteractsWithQueue;\nuse Illuminate\\Support\\Collection;\nuse Maatwebsite\\Excel\\Concerns\\WithEvents;\nuse Maatwebsite\\Excel\\Events\\ImportFailed;\nuse Maatwebsite\\Excel\\HasEventBus;\nuse Maatwebsite\\Excel\\Reader;\nuse Throwable;\n\nclass AfterImportJob implements ShouldQueue\n{\n    use HasEventBus, InteractsWithQueue, Queueable;\n\n    /**\n     * @var WithEvents\n     */\n    private $import;\n\n    /**\n     * @var Reader\n     */\n    private $reader;\n\n    /**\n     * @var iterable\n     */\n    private $dependencyIds = [];\n\n    private $interval = 60;\n\n    /**\n     * @param  object  $import\n     * @param  Reader  $reader\n     */\n    public function __construct($import, Reader $reader)\n    {\n        $this->import = $import;\n        $this->reader = $reader;\n    }\n\n    public function setInterval(int $interval)\n    {\n        $this->interval = $interval;\n    }\n\n    public function setDependencies(Collection $jobs)\n    {\n        $this->dependencyIds = $jobs->map(function (ReadChunk $job) {\n            return $job->getUniqueId();\n        })->all();\n    }\n\n    public function handle()\n    {\n        foreach ($this->dependencyIds as $id) {\n            if (!ReadChunk::isComplete($id)) {\n                // Until there is no jobs left to run we put this job back into the queue every minute\n                // Note: this will do nothing in a SyncQueue but that's desired, because in a SyncQueue jobs run in order\n                $this->release($this->interval);\n\n                return;\n            }\n        }\n\n        if ($this->import instanceof ShouldQueue && $this->import instanceof WithEvents) {\n            $this->reader->clearListeners();\n            $this->reader->registerListeners($this->import->registerEvents());\n        }\n\n        $this->reader->afterImport($this->import);\n    }\n\n    /**\n     * @param  Throwable  $e\n     */\n    public function failed(Throwable $e)\n    {\n        if ($this->import instanceof WithEvents) {\n            $this->registerListeners($this->import->registerEvents());\n            $this->raise(new ImportFailed($e));\n\n            if (method_exists($this->import, 'failed')) {\n                $this->import->failed($e);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Jobs/AppendDataToSheet.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Jobs;\n\nuse Illuminate\\Bus\\Queueable;\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Illuminate\\Foundation\\Bus\\Dispatchable;\nuse Illuminate\\Queue\\InteractsWithQueue;\nuse Maatwebsite\\Excel\\Files\\TemporaryFile;\nuse Maatwebsite\\Excel\\Jobs\\Middleware\\LocalizeJob;\nuse Maatwebsite\\Excel\\Writer;\n\nclass AppendDataToSheet implements ShouldQueue\n{\n    use Queueable, Dispatchable, ProxyFailures, InteractsWithQueue;\n\n    /**\n     * @var array\n     */\n    public $data = [];\n\n    /**\n     * @var string\n     */\n    public $temporaryFile;\n\n    /**\n     * @var string\n     */\n    public $writerType;\n\n    /**\n     * @var int\n     */\n    public $sheetIndex;\n\n    /**\n     * @var object\n     */\n    public $sheetExport;\n\n    /**\n     * @param  object  $sheetExport\n     * @param  TemporaryFile  $temporaryFile\n     * @param  string  $writerType\n     * @param  int  $sheetIndex\n     * @param  array  $data\n     */\n    public function __construct($sheetExport, TemporaryFile $temporaryFile, string $writerType, int $sheetIndex, array $data)\n    {\n        $this->sheetExport   = $sheetExport;\n        $this->data          = $data;\n        $this->temporaryFile = $temporaryFile;\n        $this->writerType    = $writerType;\n        $this->sheetIndex    = $sheetIndex;\n    }\n\n    /**\n     * Get the middleware the job should be dispatched through.\n     *\n     * @return array\n     */\n    public function middleware()\n    {\n        return (method_exists($this->sheetExport, 'middleware')) ? $this->sheetExport->middleware() : [];\n    }\n\n    /**\n     * @param  Writer  $writer\n     *\n     * @throws \\PhpOffice\\PhpSpreadsheet\\Exception\n     * @throws \\PhpOffice\\PhpSpreadsheet\\Reader\\Exception\n     */\n    public function handle(Writer $writer)\n    {\n        (new LocalizeJob($this->sheetExport))->handle($this, function () use ($writer) {\n            $writer = $writer->reopen($this->temporaryFile, $this->writerType);\n\n            $sheet = $writer->getSheetByIndex($this->sheetIndex);\n\n            $sheet->appendRows($this->data, $this->sheetExport);\n\n            $writer->write($this->sheetExport, $this->temporaryFile, $this->writerType);\n        });\n    }\n}\n"
  },
  {
    "path": "src/Jobs/AppendPaginatedToSheet.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Jobs;\n\nuse Illuminate\\Bus\\Queueable;\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Illuminate\\Database\\Eloquent\\Builder as EloquentBuilder;\nuse Illuminate\\Database\\Eloquent\\Relations\\Relation;\nuse Illuminate\\Database\\Query\\Builder;\nuse Illuminate\\Foundation\\Bus\\Dispatchable;\nuse Illuminate\\Queue\\InteractsWithQueue;\nuse Laravel\\Scout\\Builder as ScoutBuilder;\nuse Maatwebsite\\Excel\\Concerns\\FromQuery;\nuse Maatwebsite\\Excel\\Files\\TemporaryFile;\nuse Maatwebsite\\Excel\\Jobs\\Middleware\\LocalizeJob;\nuse Maatwebsite\\Excel\\Writer;\n\nclass AppendPaginatedToSheet implements ShouldQueue\n{\n    use Queueable, Dispatchable, ProxyFailures, InteractsWithQueue;\n\n    /**\n     * @var TemporaryFile\n     */\n    public $temporaryFile;\n\n    /**\n     * @var string\n     */\n    public $writerType;\n\n    /**\n     * @var int\n     */\n    public $sheetIndex;\n\n    /**\n     * @var FromQuery\n     */\n    public $sheetExport;\n\n    /**\n     * @var int\n     */\n    public $page;\n\n    /**\n     * @var int\n     */\n    public $perPage;\n\n    /**\n     * @param  FromQuery  $sheetExport\n     * @param  TemporaryFile  $temporaryFile\n     * @param  string  $writerType\n     * @param  int  $sheetIndex\n     * @param  int  $page\n     * @param  int  $perPage\n     */\n    public function __construct(\n        FromQuery $sheetExport,\n        TemporaryFile $temporaryFile,\n        string $writerType,\n        int $sheetIndex,\n        int $page,\n        int $perPage\n    ) {\n        $this->sheetExport   = $sheetExport;\n        $this->temporaryFile = $temporaryFile;\n        $this->writerType    = $writerType;\n        $this->sheetIndex    = $sheetIndex;\n        $this->page          = $page;\n        $this->perPage       = $perPage;\n    }\n\n    /**\n     * Get the middleware the job should be dispatched through.\n     *\n     * @return array\n     */\n    public function middleware()\n    {\n        return (method_exists($this->sheetExport, 'middleware')) ? $this->sheetExport->middleware() : [];\n    }\n\n    /**\n     * @param  Writer  $writer\n     *\n     * @throws \\PhpOffice\\PhpSpreadsheet\\Exception\n     * @throws \\PhpOffice\\PhpSpreadsheet\\Reader\\Exception\n     */\n    public function handle(Writer $writer)\n    {\n        (new LocalizeJob($this->sheetExport))->handle($this, function () use ($writer) {\n            $writer = $writer->reopen($this->temporaryFile, $this->writerType);\n\n            $sheet = $writer->getSheetByIndex($this->sheetIndex);\n\n            $sheet->appendRows($this->chunk($this->sheetExport->query()), $this->sheetExport);\n\n            $writer->write($this->sheetExport, $this->temporaryFile, $this->writerType);\n        });\n    }\n\n    /**\n     * @param  Builder|Relation|EloquentBuilder|ScoutBuilder  $query\n     */\n    protected function chunk($query)\n    {\n        if ($query instanceof \\Laravel\\Scout\\Builder) {\n            return $query->paginate($this->perPage, 'page', $this->page)->items();\n        }\n\n        // Fallback\n        return $query->forPage($this->page, $this->perPage)->get();\n    }\n}\n"
  },
  {
    "path": "src/Jobs/AppendQueryToSheet.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Jobs;\n\nuse Illuminate\\Bus\\Queueable;\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Illuminate\\Foundation\\Bus\\Dispatchable;\nuse Illuminate\\Queue\\InteractsWithQueue;\nuse Maatwebsite\\Excel\\Concerns\\FromQuery;\nuse Maatwebsite\\Excel\\Concerns\\WithEvents;\nuse Maatwebsite\\Excel\\Events\\AfterChunk;\nuse Maatwebsite\\Excel\\Files\\TemporaryFile;\nuse Maatwebsite\\Excel\\HasEventBus;\nuse Maatwebsite\\Excel\\Jobs\\Middleware\\LocalizeJob;\nuse Maatwebsite\\Excel\\Writer;\n\nclass AppendQueryToSheet implements ShouldQueue\n{\n    use Queueable, Dispatchable, ProxyFailures, InteractsWithQueue, HasEventBus;\n\n    /**\n     * @var TemporaryFile\n     */\n    public $temporaryFile;\n\n    /**\n     * @var string\n     */\n    public $writerType;\n\n    /**\n     * @var int\n     */\n    public $sheetIndex;\n\n    /**\n     * @var FromQuery\n     */\n    public $sheetExport;\n\n    /**\n     * @var int\n     */\n    public $page;\n\n    /**\n     * @var int\n     */\n    public $chunkSize;\n\n    /**\n     * @param  FromQuery  $sheetExport\n     * @param  TemporaryFile  $temporaryFile\n     * @param  string  $writerType\n     * @param  int  $sheetIndex\n     * @param  int  $page\n     * @param  int  $chunkSize\n     */\n    public function __construct(\n        FromQuery $sheetExport,\n        TemporaryFile $temporaryFile,\n        string $writerType,\n        int $sheetIndex,\n        int $page,\n        int $chunkSize\n    ) {\n        $this->sheetExport   = $sheetExport;\n        $this->temporaryFile = $temporaryFile;\n        $this->writerType    = $writerType;\n        $this->sheetIndex    = $sheetIndex;\n        $this->page          = $page;\n        $this->chunkSize     = $chunkSize;\n    }\n\n    /**\n     * Get the middleware the job should be dispatched through.\n     *\n     * @return array\n     */\n    public function middleware()\n    {\n        return (method_exists($this->sheetExport, 'middleware')) ? $this->sheetExport->middleware() : [];\n    }\n\n    /**\n     * @param  Writer  $writer\n     *\n     * @throws \\PhpOffice\\PhpSpreadsheet\\Exception\n     * @throws \\PhpOffice\\PhpSpreadsheet\\Reader\\Exception\n     */\n    public function handle(Writer $writer)\n    {\n        (new LocalizeJob($this->sheetExport))->handle($this, function () use ($writer) {\n            if ($this->sheetExport instanceof WithEvents) {\n                $this->registerListeners($this->sheetExport->registerEvents());\n            }\n\n            $writer = $writer->reopen($this->temporaryFile, $this->writerType);\n\n            $sheet = $writer->getSheetByIndex($this->sheetIndex);\n\n            $query = $this->sheetExport->query()->forPage($this->page, $this->chunkSize);\n\n            $sheet->appendRows($query->get(), $this->sheetExport);\n\n            $writer->write($this->sheetExport, $this->temporaryFile, $this->writerType);\n\n            $this->raise(new AfterChunk($sheet, $this->sheetExport, ($this->page - 1) * $this->chunkSize));\n            $this->clearListeners();\n        });\n    }\n}\n"
  },
  {
    "path": "src/Jobs/AppendViewToSheet.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Jobs;\n\nuse Illuminate\\Bus\\Queueable;\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Illuminate\\Foundation\\Bus\\Dispatchable;\nuse Illuminate\\Queue\\InteractsWithQueue;\nuse Maatwebsite\\Excel\\Concerns\\FromView;\nuse Maatwebsite\\Excel\\Files\\TemporaryFile;\nuse Maatwebsite\\Excel\\Jobs\\Middleware\\LocalizeJob;\nuse Maatwebsite\\Excel\\Writer;\n\nclass AppendViewToSheet implements ShouldQueue\n{\n    use Queueable, Dispatchable, InteractsWithQueue;\n\n    /**\n     * @var TemporaryFile\n     */\n    public $temporaryFile;\n\n    /**\n     * @var string\n     */\n    public $writerType;\n\n    /**\n     * @var int\n     */\n    public $sheetIndex;\n\n    /**\n     * @var FromView\n     */\n    public $sheetExport;\n\n    /**\n     * @param  FromView  $sheetExport\n     * @param  TemporaryFile  $temporaryFile\n     * @param  string  $writerType\n     * @param  int  $sheetIndex\n     * @param  array  $data\n     */\n    public function __construct(FromView $sheetExport, TemporaryFile $temporaryFile, string $writerType, int $sheetIndex)\n    {\n        $this->sheetExport   = $sheetExport;\n        $this->temporaryFile = $temporaryFile;\n        $this->writerType    = $writerType;\n        $this->sheetIndex    = $sheetIndex;\n    }\n\n    /**\n     * Get the middleware the job should be dispatched through.\n     *\n     * @return array\n     */\n    public function middleware()\n    {\n        return (method_exists($this->sheetExport, 'middleware')) ? $this->sheetExport->middleware() : [];\n    }\n\n    /**\n     * @param  Writer  $writer\n     *\n     * @throws \\PhpOffice\\PhpSpreadsheet\\Exception\n     * @throws \\PhpOffice\\PhpSpreadsheet\\Reader\\Exception\n     */\n    public function handle(Writer $writer)\n    {\n        (new LocalizeJob($this->sheetExport))->handle($this, function () use ($writer) {\n            $writer = $writer->reopen($this->temporaryFile, $this->writerType);\n\n            $sheet = $writer->getSheetByIndex($this->sheetIndex);\n\n            $sheet->fromView($this->sheetExport, $this->sheetIndex);\n\n            $writer->write($this->sheetExport, $this->temporaryFile, $this->writerType);\n        });\n    }\n}\n"
  },
  {
    "path": "src/Jobs/CloseSheet.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Jobs;\n\nuse Illuminate\\Bus\\Queueable;\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Maatwebsite\\Excel\\Concerns\\WithEvents;\nuse Maatwebsite\\Excel\\Files\\TemporaryFile;\nuse Maatwebsite\\Excel\\Writer;\n\nclass CloseSheet implements ShouldQueue\n{\n    use Queueable, ProxyFailures;\n\n    /**\n     * @var object\n     */\n    private $sheetExport;\n\n    /**\n     * @var string\n     */\n    private $temporaryFile;\n\n    /**\n     * @var string\n     */\n    private $writerType;\n\n    /**\n     * @var int\n     */\n    private $sheetIndex;\n\n    /**\n     * @param  object  $sheetExport\n     * @param  TemporaryFile  $temporaryFile\n     * @param  string  $writerType\n     * @param  int  $sheetIndex\n     */\n    public function __construct($sheetExport, TemporaryFile $temporaryFile, string $writerType, int $sheetIndex)\n    {\n        $this->sheetExport   = $sheetExport;\n        $this->temporaryFile = $temporaryFile;\n        $this->writerType    = $writerType;\n        $this->sheetIndex    = $sheetIndex;\n    }\n\n    /**\n     * @param  Writer  $writer\n     *\n     * @throws \\PhpOffice\\PhpSpreadsheet\\Exception\n     * @throws \\PhpOffice\\PhpSpreadsheet\\Reader\\Exception\n     */\n    public function handle(Writer $writer)\n    {\n        $writer = $writer->reopen(\n            $this->temporaryFile,\n            $this->writerType\n        );\n\n        $sheet = $writer->getSheetByIndex($this->sheetIndex);\n\n        if ($this->sheetExport instanceof WithEvents) {\n            $sheet->registerListeners($this->sheetExport->registerEvents());\n        }\n\n        $sheet->close($this->sheetExport);\n\n        $writer->write(\n            $this->sheetExport,\n            $this->temporaryFile,\n            $this->writerType\n        );\n    }\n}\n"
  },
  {
    "path": "src/Jobs/ExtendedQueueable.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Jobs;\n\nuse Illuminate\\Bus\\Queueable;\n\ntrait ExtendedQueueable\n{\n    use Queueable {\n        chain as originalChain;\n    }\n\n    /**\n     * @param  $chain\n     * @return $this\n     */\n    public function chain($chain)\n    {\n        collect($chain)->each(function ($job) {\n            $serialized      = method_exists($this, 'serializeJob') ? $this->serializeJob($job) : serialize($job);\n            $this->chained[] = $serialized;\n        });\n\n        return $this;\n    }\n}\n"
  },
  {
    "path": "src/Jobs/Middleware/LocalizeJob.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Jobs\\Middleware;\n\nuse Closure;\nuse Illuminate\\Contracts\\Translation\\HasLocalePreference;\nuse Illuminate\\Support\\Traits\\Localizable;\n\nclass LocalizeJob\n{\n    use Localizable;\n\n    /**\n     * @var object\n     */\n    private $localizable;\n\n    /**\n     * LocalizeJob constructor.\n     *\n     * @param  object  $localizable\n     */\n    public function __construct($localizable)\n    {\n        $this->localizable = $localizable;\n    }\n\n    /**\n     * Handles the job.\n     *\n     * @param  mixed  $job\n     * @param  Closure  $next\n     * @return mixed\n     */\n    public function handle($job, Closure $next)\n    {\n        $locale = value(function () {\n            if ($this->localizable instanceof HasLocalePreference) {\n                return $this->localizable->preferredLocale();\n            }\n\n            return null;\n        });\n\n        return $this->withLocale($locale, function () use ($next, $job) {\n            return $next($job);\n        });\n    }\n}\n"
  },
  {
    "path": "src/Jobs/ProxyFailures.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Jobs;\n\nuse Throwable;\n\ntrait ProxyFailures\n{\n    /**\n     * @param  Throwable  $e\n     */\n    public function failed(Throwable $e)\n    {\n        if (method_exists($this->sheetExport, 'failed')) {\n            $this->sheetExport->failed($e);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Jobs/QueueExport.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Jobs;\n\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Illuminate\\Foundation\\Bus\\Dispatchable;\nuse Illuminate\\Queue\\InteractsWithQueue;\nuse Maatwebsite\\Excel\\Concerns\\WithMultipleSheets;\nuse Maatwebsite\\Excel\\Exceptions\\NoSheetsFoundException;\nuse Maatwebsite\\Excel\\Files\\TemporaryFile;\nuse Maatwebsite\\Excel\\Jobs\\Middleware\\LocalizeJob;\nuse Maatwebsite\\Excel\\Writer;\nuse Throwable;\n\nclass QueueExport implements ShouldQueue\n{\n    use ExtendedQueueable, Dispatchable, InteractsWithQueue;\n\n    /**\n     * @var object\n     */\n    public $export;\n\n    /**\n     * @var string\n     */\n    private $writerType;\n\n    /**\n     * @var TemporaryFile\n     */\n    private $temporaryFile;\n\n    /**\n     * @param  object  $export\n     * @param  TemporaryFile  $temporaryFile\n     * @param  string  $writerType\n     */\n    public function __construct($export, TemporaryFile $temporaryFile, string $writerType)\n    {\n        $this->export        = $export;\n        $this->writerType    = $writerType;\n        $this->temporaryFile = $temporaryFile;\n    }\n\n    /**\n     * Get the middleware the job should be dispatched through.\n     *\n     * @return array\n     */\n    public function middleware()\n    {\n        return (method_exists($this->export, 'middleware')) ? $this->export->middleware() : [];\n    }\n\n    /**\n     * @param  Writer  $writer\n     *\n     * @throws \\PhpOffice\\PhpSpreadsheet\\Exception\n     */\n    public function handle(Writer $writer)\n    {\n        (new LocalizeJob($this->export))->handle($this, function () use ($writer) {\n            $writer->open($this->export);\n\n            $sheetExports = [$this->export];\n            if ($this->export instanceof WithMultipleSheets) {\n                $sheetExports = $this->export->sheets();\n            }\n\n            if (count($sheetExports) === 0) {\n                throw new NoSheetsFoundException('Your export did not return any sheet export instances, please make sure your sheets() method always at least returns one instance.');\n            }\n\n            // Pre-create the worksheets\n            foreach ($sheetExports as $sheetIndex => $sheetExport) {\n                $sheet = $writer->addNewSheet($sheetIndex);\n                $sheet->open($sheetExport);\n            }\n\n            // Write to temp file with empty sheets.\n            $writer->write($this->export, $this->temporaryFile, $this->writerType);\n        });\n    }\n\n    /**\n     * @param  Throwable  $e\n     */\n    public function failed(Throwable $e)\n    {\n        if (method_exists($this->export, 'failed')) {\n            $this->export->failed($e);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Jobs/QueueImport.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Jobs;\n\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Illuminate\\Foundation\\Bus\\Dispatchable;\n\nclass QueueImport implements ShouldQueue\n{\n    use ExtendedQueueable, Dispatchable;\n\n    /**\n     * @var int\n     */\n    public $tries;\n\n    /**\n     * @var int\n     */\n    public $timeout;\n\n    /**\n     * @param  ShouldQueue  $import\n     */\n    public function __construct(?ShouldQueue $import = null)\n    {\n        if ($import) {\n            $this->timeout = $import->timeout ?? null;\n            $this->tries   = $import->tries ?? null;\n        }\n    }\n\n    public function handle()\n    {\n        //\n    }\n}\n"
  },
  {
    "path": "src/Jobs/ReadChunk.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Jobs;\n\nuse Illuminate\\Bus\\Queueable;\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Illuminate\\Queue\\InteractsWithQueue;\nuse Illuminate\\Support\\Facades\\Cache;\nuse Maatwebsite\\Excel\\Concerns\\WithChunkReading;\nuse Maatwebsite\\Excel\\Concerns\\WithCustomValueBinder;\nuse Maatwebsite\\Excel\\Concerns\\WithEvents;\nuse Maatwebsite\\Excel\\Events\\AfterChunk;\nuse Maatwebsite\\Excel\\Events\\ImportFailed;\nuse Maatwebsite\\Excel\\Files\\RemoteTemporaryFile;\nuse Maatwebsite\\Excel\\Files\\TemporaryFile;\nuse Maatwebsite\\Excel\\Filters\\ChunkReadFilter;\nuse Maatwebsite\\Excel\\HasEventBus;\nuse Maatwebsite\\Excel\\Imports\\HeadingRowExtractor;\nuse Maatwebsite\\Excel\\Sheet;\nuse Maatwebsite\\Excel\\Transactions\\TransactionHandler;\nuse PhpOffice\\PhpSpreadsheet\\Cell\\Cell;\nuse PhpOffice\\PhpSpreadsheet\\Reader\\IReader;\nuse Throwable;\n\nclass ReadChunk implements ShouldQueue\n{\n    use Queueable, HasEventBus, InteractsWithQueue;\n\n    /**\n     * @var int\n     */\n    public $timeout;\n\n    /**\n     * @var int\n     */\n    public $tries;\n\n    /**\n     * @var int\n     */\n    public $maxExceptions;\n\n    /**\n     * @var int\n     */\n    public $backoff;\n\n    /**\n     * @var string\n     */\n    public $queue;\n\n    /**\n     * @var string\n     */\n    public $connection;\n\n    /**\n     * @var WithChunkReading\n     */\n    private $import;\n\n    /**\n     * @var IReader\n     */\n    private $reader;\n\n    /**\n     * @var TemporaryFile\n     */\n    private $temporaryFile;\n\n    /**\n     * @var string\n     */\n    private $sheetName;\n\n    /**\n     * @var object\n     */\n    private $sheetImport;\n\n    /**\n     * @var int\n     */\n    private $startRow;\n\n    /**\n     * @var int\n     */\n    private $chunkSize;\n\n    /**\n     * @var string\n     */\n    private $uniqueId;\n\n    /**\n     * @param  WithChunkReading  $import\n     * @param  IReader  $reader\n     * @param  TemporaryFile  $temporaryFile\n     * @param  string  $sheetName\n     * @param  object  $sheetImport\n     * @param  int  $startRow\n     * @param  int  $chunkSize\n     */\n    public function __construct(WithChunkReading $import, IReader $reader, TemporaryFile $temporaryFile, string $sheetName, $sheetImport, int $startRow, int $chunkSize)\n    {\n        $this->import        = $import;\n        $this->reader        = $reader;\n        $this->temporaryFile = $temporaryFile;\n        $this->sheetName     = $sheetName;\n        $this->sheetImport   = $sheetImport;\n        $this->startRow      = $startRow;\n        $this->chunkSize     = $chunkSize;\n        $this->timeout       = $import->timeout ?? null;\n        $this->tries         = $import->tries ?? null;\n        $this->maxExceptions = $import->maxExceptions ?? null;\n        $this->backoff       = method_exists($import, 'backoff') ? $import->backoff() : ($import->backoff ?? null);\n        $this->connection    = property_exists($import, 'connection') ? $import->connection : null;\n        $this->queue         = property_exists($import, 'queue') ? $import->queue : null;\n    }\n\n    public function getUniqueId(): string\n    {\n        if (!isset($this->uniqueId)) {\n            $this->uniqueId = uniqid();\n            Cache::set('laravel-excel/read-chunk/' . $this->uniqueId, true);\n        }\n\n        return $this->uniqueId;\n    }\n\n    public static function isComplete(string $id): bool\n    {\n        return !Cache::has('laravel-excel/read-chunk/' . $id);\n    }\n\n    /**\n     * Get the middleware the job should be dispatched through.\n     *\n     * @return array\n     */\n    public function middleware()\n    {\n        return (method_exists($this->import, 'middleware')) ? $this->import->middleware() : [];\n    }\n\n    /**\n     * Determine the time at which the job should timeout.\n     *\n     * @return \\DateTime\n     */\n    public function retryUntil()\n    {\n        return (method_exists($this->import, 'retryUntil')) ? $this->import->retryUntil() : null;\n    }\n\n    /**\n     * @param  TransactionHandler  $transaction\n     *\n     * @throws \\Maatwebsite\\Excel\\Exceptions\\SheetNotFoundException\n     * @throws \\PhpOffice\\PhpSpreadsheet\\Reader\\Exception\n     */\n    public function handle(TransactionHandler $transaction)\n    {\n        if (method_exists($this->import, 'setChunkOffset')) {\n            $this->import->setChunkOffset($this->startRow);\n        }\n\n        if (method_exists($this->sheetImport, 'setChunkOffset')) {\n            $this->sheetImport->setChunkOffset($this->startRow);\n        }\n\n        if ($this->sheetImport instanceof WithCustomValueBinder) {\n            Cell::setValueBinder($this->sheetImport);\n        }\n\n        $headingRow = HeadingRowExtractor::headingRow($this->sheetImport);\n\n        $filter = new ChunkReadFilter(\n            $headingRow,\n            $this->startRow,\n            $this->chunkSize,\n            $this->sheetName\n        );\n\n        $this->reader->setReadFilter($filter);\n        $this->reader->setReadDataOnly(config('excel.imports.read_only', true));\n        $this->reader->setReadEmptyCells(!config('excel.imports.ignore_empty', false));\n\n        $spreadsheet = $this->reader->load(\n            $this->temporaryFile->sync()->getLocalPath()\n        );\n\n        $sheet = Sheet::byName(\n            $spreadsheet,\n            $this->sheetName\n        );\n\n        if ($sheet->getHighestRow() < $this->startRow) {\n            $sheet->disconnect();\n\n            $this->cleanUpTempFile();\n\n            return;\n        }\n\n        $transaction(function () use ($sheet) {\n            $sheet->import(\n                $this->sheetImport,\n                $this->startRow\n            );\n\n            $sheet->disconnect();\n\n            $this->cleanUpTempFile();\n\n            $sheet->raise(new AfterChunk($sheet, $this->import, $this->startRow));\n        });\n    }\n\n    /**\n     * @param  Throwable  $e\n     */\n    public function failed(Throwable $e)\n    {\n        $this->cleanUpTempFile(true);\n\n        if ($this->import instanceof WithEvents) {\n            $this->registerListeners($this->import->registerEvents());\n            $this->raise(new ImportFailed($e));\n\n            if (method_exists($this->import, 'failed')) {\n                $this->import->failed($e);\n            }\n        }\n    }\n\n    private function cleanUpTempFile(bool $force = false): bool\n    {\n        if (!empty($this->uniqueId)) {\n            Cache::delete('laravel-excel/read-chunk/' . $this->uniqueId);\n        }\n\n        if (!$force && !config('excel.temporary_files.force_resync_remote')) {\n            return true;\n        }\n\n        if (!$this->temporaryFile instanceof RemoteTemporaryFile) {\n            return true;\n        }\n\n        return $this->temporaryFile->deleteLocalCopy();\n    }\n}\n"
  },
  {
    "path": "src/Jobs/StoreQueuedExport.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Jobs;\n\nuse Illuminate\\Bus\\Queueable;\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Maatwebsite\\Excel\\Files\\Filesystem;\nuse Maatwebsite\\Excel\\Files\\TemporaryFile;\n\nclass StoreQueuedExport implements ShouldQueue\n{\n    use Queueable;\n\n    /**\n     * @var string\n     */\n    private $filePath;\n\n    /**\n     * @var string|null\n     */\n    private $disk;\n\n    /**\n     * @var TemporaryFile\n     */\n    private $temporaryFile;\n    /**\n     * @var array|string\n     */\n    private $diskOptions;\n\n    /**\n     * @param  TemporaryFile  $temporaryFile\n     * @param  string  $filePath\n     * @param  string|null  $disk\n     * @param  array|string  $diskOptions\n     */\n    public function __construct(TemporaryFile $temporaryFile, string $filePath, ?string $disk = null, $diskOptions = [])\n    {\n        $this->disk          = $disk;\n        $this->filePath      = $filePath;\n        $this->temporaryFile = $temporaryFile;\n        $this->diskOptions   = $diskOptions;\n    }\n\n    /**\n     * @param  Filesystem  $filesystem\n     */\n    public function handle(Filesystem $filesystem)\n    {\n        $filesystem->disk($this->disk, $this->diskOptions)->copy(\n            $this->temporaryFile,\n            $this->filePath\n        );\n\n        $this->temporaryFile->delete();\n    }\n}\n"
  },
  {
    "path": "src/MappedReader.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel;\n\nuse Illuminate\\Support\\Collection;\nuse Maatwebsite\\Excel\\Concerns\\ToArray;\nuse Maatwebsite\\Excel\\Concerns\\ToCollection;\nuse Maatwebsite\\Excel\\Concerns\\ToModel;\nuse Maatwebsite\\Excel\\Concerns\\WithCalculatedFormulas;\nuse Maatwebsite\\Excel\\Concerns\\WithFormatData;\nuse Maatwebsite\\Excel\\Concerns\\WithMappedCells;\nuse PhpOffice\\PhpSpreadsheet\\Worksheet\\Worksheet;\n\nclass MappedReader\n{\n    /**\n     * @param  WithMappedCells  $import\n     * @param  Worksheet  $worksheet\n     *\n     * @throws \\PhpOffice\\PhpSpreadsheet\\Exception\n     */\n    public function map(WithMappedCells $import, Worksheet $worksheet)\n    {\n        $mapped = $import->mapping();\n        array_walk_recursive($mapped, function (&$coordinate) use ($import, $worksheet) {\n            $cell = Cell::make($worksheet, $coordinate);\n\n            $coordinate = $cell->getValue(\n                null,\n                $import instanceof WithCalculatedFormulas,\n                $import instanceof WithFormatData\n            );\n        });\n\n        if ($import instanceof ToModel) {\n            $model = $import->model($mapped);\n\n            if ($model) {\n                $model->saveOrFail();\n            }\n        }\n\n        if ($import instanceof ToCollection) {\n            $import->collection(new Collection($mapped));\n        }\n\n        if ($import instanceof ToArray) {\n            $import->array($mapped);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Middleware/CellMiddleware.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Middleware;\n\nabstract class CellMiddleware\n{\n    /**\n     * @param  mixed  $value\n     * @return mixed\n     */\n    abstract public function __invoke($value, callable $next);\n}\n"
  },
  {
    "path": "src/Middleware/ConvertEmptyCellValuesToNull.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Middleware;\n\nclass ConvertEmptyCellValuesToNull extends CellMiddleware\n{\n    /**\n     * @param  mixed  $value\n     * @return mixed\n     */\n    public function __invoke($value, callable $next)\n    {\n        return $next(\n            $value === '' ? null : $value\n        );\n    }\n}\n"
  },
  {
    "path": "src/Middleware/TrimCellValue.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Middleware;\n\nclass TrimCellValue extends CellMiddleware\n{\n    /**\n     * @param  mixed  $value\n     * @return mixed\n     */\n    public function __invoke($value, callable $next)\n    {\n        if (!is_string($value)) {\n            return $next($value);\n        }\n\n        // Remove whitespace, BOM and zero width spaces.\n        $cleaned = preg_replace('~^[\\s\\x{FEFF}\\x{200B}]+|[\\s\\x{FEFF}\\x{200B}]+$~u', '', $value) ?? trim($value);\n\n        return $next($cleaned);\n    }\n}\n"
  },
  {
    "path": "src/Mixins/DownloadCollectionMixin.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Mixins;\n\nuse Illuminate\\Contracts\\Support\\Arrayable;\nuse Illuminate\\Support\\Collection;\nuse Maatwebsite\\Excel\\Concerns\\Exportable;\nuse Maatwebsite\\Excel\\Concerns\\FromCollection;\nuse Maatwebsite\\Excel\\Concerns\\WithHeadings;\nuse Maatwebsite\\Excel\\Sheet;\n\nclass DownloadCollectionMixin\n{\n    /**\n     * @return callable\n     */\n    public function downloadExcel()\n    {\n        return function (string $fileName, ?string $writerType = null, $withHeadings = false, array $responseHeaders = []) {\n            $export = new class($this, $withHeadings) implements FromCollection, WithHeadings\n            {\n                use Exportable;\n\n                /**\n                 * @var bool\n                 */\n                private $withHeadings;\n\n                /**\n                 * @var Collection\n                 */\n                private $collection;\n\n                /**\n                 * @param  Collection  $collection\n                 * @param  bool  $withHeading\n                 */\n                public function __construct(Collection $collection, bool $withHeading = false)\n                {\n                    $this->collection   = $collection->toBase();\n                    $this->withHeadings = $withHeading;\n                }\n\n                /**\n                 * @return Collection\n                 */\n                public function collection()\n                {\n                    return $this->collection;\n                }\n\n                /**\n                 * @return array\n                 */\n                public function headings(): array\n                {\n                    if (!$this->withHeadings) {\n                        return [];\n                    }\n\n                    $firstRow = $this->collection->first();\n\n                    if ($firstRow instanceof Arrayable || \\is_object($firstRow)) {\n                        return array_keys(Sheet::mapArraybleRow($firstRow));\n                    }\n\n                    return $this->collection->collapse()->keys()->all();\n                }\n            };\n\n            return $export->download($fileName, $writerType, $responseHeaders);\n        };\n    }\n}\n"
  },
  {
    "path": "src/Mixins/DownloadQueryMacro.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Mixins;\n\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Maatwebsite\\Excel\\Concerns\\Exportable;\nuse Maatwebsite\\Excel\\Concerns\\FromQuery;\nuse Maatwebsite\\Excel\\Concerns\\WithHeadings;\nuse Maatwebsite\\Excel\\Sheet;\n\nclass DownloadQueryMacro\n{\n    public function __invoke()\n    {\n        return function (string $fileName, ?string $writerType = null, $withHeadings = false) {\n            $export = new class($this, $withHeadings) implements FromQuery, WithHeadings\n            {\n                use Exportable;\n\n                /**\n                 * @var bool\n                 */\n                private $withHeadings;\n\n                /**\n                 * @var Builder\n                 */\n                private $query;\n\n                /**\n                 * @param  $query\n                 * @param  bool  $withHeadings\n                 */\n                public function __construct($query, bool $withHeadings = false)\n                {\n                    $this->query        = $query;\n                    $this->withHeadings = $withHeadings;\n                }\n\n                /**\n                 * @return Builder\n                 */\n                public function query()\n                {\n                    return $this->query;\n                }\n\n                /**\n                 * @return array\n                 */\n                public function headings(): array\n                {\n                    if (!$this->withHeadings) {\n                        return [];\n                    }\n\n                    $firstRow = (clone $this->query)->first();\n\n                    if ($firstRow) {\n                        return array_keys(Sheet::mapArraybleRow($firstRow));\n                    }\n\n                    return [];\n                }\n            };\n\n            return $export->download($fileName, $writerType);\n        };\n    }\n}\n"
  },
  {
    "path": "src/Mixins/ImportAsMacro.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Mixins;\n\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Maatwebsite\\Excel\\Concerns\\Importable;\nuse Maatwebsite\\Excel\\Concerns\\ToModel;\n\nclass ImportAsMacro\n{\n    public function __invoke()\n    {\n        return function (string $filename, callable $mapping, ?string $disk = null, ?string $readerType = null) {\n            $import = new class(get_class($this->getModel()), $mapping) implements ToModel\n            {\n                use Importable;\n\n                /**\n                 * @var string\n                 */\n                private $model;\n\n                /**\n                 * @var callable\n                 */\n                private $mapping;\n\n                /**\n                 * @param  string  $model\n                 * @param  callable  $mapping\n                 */\n                public function __construct(string $model, callable $mapping)\n                {\n                    $this->model   = $model;\n                    $this->mapping = $mapping;\n                }\n\n                /**\n                 * @param  array  $row\n                 * @return Model|Model[]|null\n                 */\n                public function model(array $row)\n                {\n                    return (new $this->model)->fill(\n                        ($this->mapping)($row)\n                    );\n                }\n            };\n\n            return $import->import($filename, $disk, $readerType);\n        };\n    }\n}\n"
  },
  {
    "path": "src/Mixins/ImportMacro.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Mixins;\n\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Maatwebsite\\Excel\\Concerns\\Importable;\nuse Maatwebsite\\Excel\\Concerns\\ToModel;\nuse Maatwebsite\\Excel\\Concerns\\WithHeadingRow;\n\nclass ImportMacro\n{\n    public function __invoke()\n    {\n        return function (string $filename, ?string $disk = null, ?string $readerType = null) {\n            $import = new class(get_class($this->getModel())) implements ToModel, WithHeadingRow\n            {\n                use Importable;\n\n                /**\n                 * @var string\n                 */\n                private $model;\n\n                /**\n                 * @param  string  $model\n                 */\n                public function __construct(string $model)\n                {\n                    $this->model = $model;\n                }\n\n                /**\n                 * @param  array  $row\n                 * @return Model|Model[]|null\n                 */\n                public function model(array $row)\n                {\n                    return (new $this->model)->fill($row);\n                }\n            };\n\n            return $import->import($filename, $disk, $readerType);\n        };\n    }\n}\n"
  },
  {
    "path": "src/Mixins/StoreCollectionMixin.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Mixins;\n\nuse Illuminate\\Support\\Collection;\nuse Maatwebsite\\Excel\\Concerns\\Exportable;\nuse Maatwebsite\\Excel\\Concerns\\FromCollection;\nuse Maatwebsite\\Excel\\Concerns\\WithHeadings;\n\nclass StoreCollectionMixin\n{\n    /**\n     * @return callable\n     */\n    public function storeExcel()\n    {\n        return function (string $filePath, ?string $disk = null, ?string $writerType = null, $withHeadings = false) {\n            $export = new class($this, $withHeadings) implements FromCollection, WithHeadings\n            {\n                use Exportable;\n\n                /**\n                 * @var bool\n                 */\n                private $withHeadings;\n\n                /**\n                 * @var Collection\n                 */\n                private $collection;\n\n                /**\n                 * @param  Collection  $collection\n                 * @param  bool  $withHeadings\n                 */\n                public function __construct(Collection $collection, bool $withHeadings = false)\n                {\n                    $this->collection   = $collection->toBase();\n                    $this->withHeadings = $withHeadings;\n                }\n\n                /**\n                 * @return Collection\n                 */\n                public function collection()\n                {\n                    return $this->collection;\n                }\n\n                /**\n                 * @return array\n                 */\n                public function headings(): array\n                {\n                    if (!$this->withHeadings) {\n                        return [];\n                    }\n\n                    return is_array($first = $this->collection->first())\n                        ? $this->collection->collapse()->keys()->all()\n                        : array_keys($first->toArray());\n                }\n            };\n\n            return $export->store($filePath, $disk, $writerType);\n        };\n    }\n}\n"
  },
  {
    "path": "src/Mixins/StoreQueryMacro.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Mixins;\n\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Maatwebsite\\Excel\\Concerns\\Exportable;\nuse Maatwebsite\\Excel\\Concerns\\FromQuery;\nuse Maatwebsite\\Excel\\Concerns\\WithHeadings;\nuse Maatwebsite\\Excel\\Sheet;\n\nclass StoreQueryMacro\n{\n    public function __invoke()\n    {\n        return function (string $filePath, ?string $disk = null, ?string $writerType = null, $withHeadings = false) {\n            $export = new class($this, $withHeadings) implements FromQuery, WithHeadings\n            {\n                use Exportable;\n\n                /**\n                 * @var bool\n                 */\n                private $withHeadings;\n\n                /**\n                 * @var Builder\n                 */\n                private $query;\n\n                /**\n                 * @param  $query\n                 * @param  bool  $withHeadings\n                 */\n                public function __construct($query, bool $withHeadings = false)\n                {\n                    $this->query        = $query;\n                    $this->withHeadings = $withHeadings;\n                }\n\n                /**\n                 * @return Builder\n                 */\n                public function query()\n                {\n                    return $this->query;\n                }\n\n                /**\n                 * @return array\n                 */\n                public function headings(): array\n                {\n                    if (!$this->withHeadings) {\n                        return [];\n                    }\n\n                    $firstRow = (clone $this->query)->first();\n\n                    if ($firstRow) {\n                        return array_keys(Sheet::mapArraybleRow($firstRow));\n                    }\n\n                    return [];\n                }\n            };\n\n            return $export->store($filePath, $disk, $writerType);\n        };\n    }\n}\n"
  },
  {
    "path": "src/QueuedWriter.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel;\n\nuse Illuminate\\Foundation\\Bus\\PendingDispatch;\nuse Illuminate\\Support\\Collection;\nuse Illuminate\\Support\\LazyCollection;\nuse Maatwebsite\\Excel\\Concerns\\FromCollection;\nuse Maatwebsite\\Excel\\Concerns\\FromQuery;\nuse Maatwebsite\\Excel\\Concerns\\FromView;\nuse Maatwebsite\\Excel\\Concerns\\WithCustomChunkSize;\nuse Maatwebsite\\Excel\\Concerns\\WithCustomQuerySize;\nuse Maatwebsite\\Excel\\Concerns\\WithMultipleSheets;\nuse Maatwebsite\\Excel\\Files\\TemporaryFile;\nuse Maatwebsite\\Excel\\Files\\TemporaryFileFactory;\nuse Maatwebsite\\Excel\\Jobs\\AppendDataToSheet;\nuse Maatwebsite\\Excel\\Jobs\\AppendPaginatedToSheet;\nuse Maatwebsite\\Excel\\Jobs\\AppendQueryToSheet;\nuse Maatwebsite\\Excel\\Jobs\\AppendViewToSheet;\nuse Maatwebsite\\Excel\\Jobs\\CloseSheet;\nuse Maatwebsite\\Excel\\Jobs\\QueueExport;\nuse Maatwebsite\\Excel\\Jobs\\StoreQueuedExport;\nuse Traversable;\n\nclass QueuedWriter\n{\n    /**\n     * @var Writer\n     */\n    protected $writer;\n\n    /**\n     * @var int\n     */\n    protected $chunkSize;\n\n    /**\n     * @var TemporaryFileFactory\n     */\n    protected $temporaryFileFactory;\n\n    /**\n     * @param  Writer  $writer\n     * @param  TemporaryFileFactory  $temporaryFileFactory\n     */\n    public function __construct(Writer $writer, TemporaryFileFactory $temporaryFileFactory)\n    {\n        $this->writer               = $writer;\n        $this->chunkSize            = config('excel.exports.chunk_size', 1000);\n        $this->temporaryFileFactory = $temporaryFileFactory;\n    }\n\n    /**\n     * @param  object  $export\n     * @param  string  $filePath\n     * @param  string  $disk\n     * @param  string|null  $writerType\n     * @param  array|string  $diskOptions\n     * @return \\Illuminate\\Foundation\\Bus\\PendingDispatch\n     */\n    public function store($export, string $filePath, ?string $disk = null, ?string $writerType = null, $diskOptions = [])\n    {\n        $extension     = pathinfo($filePath, PATHINFO_EXTENSION);\n        $temporaryFile = $this->temporaryFileFactory->make($extension);\n\n        $jobs = $this->buildExportJobs($export, $temporaryFile, $writerType);\n\n        $jobs->push(new StoreQueuedExport(\n            $temporaryFile,\n            $filePath,\n            $disk,\n            $diskOptions\n        ));\n\n        return new PendingDispatch(\n            (new QueueExport($export, $temporaryFile, $writerType))->chain($jobs->toArray())\n        );\n    }\n\n    /**\n     * @param  object  $export\n     * @param  TemporaryFile  $temporaryFile\n     * @param  string  $writerType\n     * @return Collection\n     */\n    private function buildExportJobs($export, TemporaryFile $temporaryFile, string $writerType): Collection\n    {\n        $sheetExports = [$export];\n        if ($export instanceof WithMultipleSheets) {\n            $sheetExports = $export->sheets();\n        }\n\n        $jobs = new Collection;\n        foreach ($sheetExports as $sheetIndex => $sheetExport) {\n            if ($sheetExport instanceof FromCollection) {\n                $jobs = $jobs->merge($this->exportCollection($sheetExport, $temporaryFile, $writerType, $sheetIndex));\n            } elseif ($sheetExport instanceof FromQuery) {\n                $jobs = $jobs->merge($this->exportQuery($sheetExport, $temporaryFile, $writerType, $sheetIndex));\n            } elseif ($sheetExport instanceof FromView) {\n                $jobs = $jobs->merge($this->exportView($sheetExport, $temporaryFile, $writerType, $sheetIndex));\n            }\n\n            $jobs->push(new CloseSheet($sheetExport, $temporaryFile, $writerType, $sheetIndex));\n        }\n\n        return $jobs;\n    }\n\n    /**\n     * @param  FromCollection  $export\n     * @param  TemporaryFile  $temporaryFile\n     * @param  string  $writerType\n     * @param  int  $sheetIndex\n     * @return Collection|LazyCollection\n     */\n    private function exportCollection(\n        FromCollection $export,\n        TemporaryFile $temporaryFile,\n        string $writerType,\n        int $sheetIndex\n    ) {\n        return $export\n            ->collection()\n            ->chunk($this->getChunkSize($export))\n            ->map(function ($rows) use ($writerType, $temporaryFile, $sheetIndex, $export) {\n                if ($rows instanceof Traversable) {\n                    $rows = iterator_to_array($rows);\n                }\n\n                return new AppendDataToSheet(\n                    $export,\n                    $temporaryFile,\n                    $writerType,\n                    $sheetIndex,\n                    $rows\n                );\n            });\n    }\n\n    /**\n     * @param  FromQuery  $export\n     * @param  TemporaryFile  $temporaryFile\n     * @param  string  $writerType\n     * @param  int  $sheetIndex\n     * @return Collection\n     */\n    private function exportQuery(\n        FromQuery $export,\n        TemporaryFile $temporaryFile,\n        string $writerType,\n        int $sheetIndex\n    ): Collection {\n        $query = $export->query();\n\n        if ($query instanceof \\Laravel\\Scout\\Builder) {\n            return $this->exportScout($export, $temporaryFile, $writerType, $sheetIndex);\n        }\n\n        $count = $export instanceof WithCustomQuerySize ? $export->querySize() : $query->count();\n        $spins = ceil($count / $this->getChunkSize($export));\n\n        $jobs = new Collection();\n\n        for ($page = 1; $page <= $spins; $page++) {\n            $jobs->push(new AppendQueryToSheet(\n                $export,\n                $temporaryFile,\n                $writerType,\n                $sheetIndex,\n                $page,\n                $this->getChunkSize($export)\n            ));\n        }\n\n        return $jobs;\n    }\n\n    /**\n     * @param  FromQuery  $export\n     * @param  TemporaryFile  $temporaryFile\n     * @param  string  $writerType\n     * @param  int  $sheetIndex\n     * @return Collection\n     */\n    private function exportScout(\n        FromQuery $export,\n        TemporaryFile $temporaryFile,\n        string $writerType,\n        int $sheetIndex\n    ): Collection {\n        $jobs = new Collection();\n\n        $chunk = $export->query()->paginate($this->getChunkSize($export));\n        // Append first page\n        $jobs->push(new AppendDataToSheet(\n            $export,\n            $temporaryFile,\n            $writerType,\n            $sheetIndex,\n            $chunk->items()\n        ));\n\n        // Append rest of pages\n        for ($page = 2; $page <= $chunk->lastPage(); $page++) {\n            $jobs->push(new AppendPaginatedToSheet(\n                $export,\n                $temporaryFile,\n                $writerType,\n                $sheetIndex,\n                $page,\n                $this->getChunkSize($export)\n            ));\n        }\n\n        return $jobs;\n    }\n\n    /**\n     * @param  FromView  $export\n     * @param  TemporaryFile  $temporaryFile\n     * @param  string  $writerType\n     * @param  int  $sheetIndex\n     * @return Collection\n     */\n    private function exportView(\n        FromView $export,\n        TemporaryFile $temporaryFile,\n        string $writerType,\n        int $sheetIndex\n    ): Collection {\n        $jobs = new Collection();\n        $jobs->push(new AppendViewToSheet(\n            $export,\n            $temporaryFile,\n            $writerType,\n            $sheetIndex\n        ));\n\n        return $jobs;\n    }\n\n    /**\n     * @param  object|WithCustomChunkSize  $export\n     * @return int\n     */\n    private function getChunkSize($export): int\n    {\n        if ($export instanceof WithCustomChunkSize) {\n            return $export->chunkSize();\n        }\n\n        return $this->chunkSize;\n    }\n}\n"
  },
  {
    "path": "src/Reader.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel;\n\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Illuminate\\Support\\Collection;\nuse InvalidArgumentException;\nuse Maatwebsite\\Excel\\Concerns\\HasReferencesToOtherSheets;\nuse Maatwebsite\\Excel\\Concerns\\SkipsUnknownSheets;\nuse Maatwebsite\\Excel\\Concerns\\WithCalculatedFormulas;\nuse Maatwebsite\\Excel\\Concerns\\WithChunkReading;\nuse Maatwebsite\\Excel\\Concerns\\WithCustomValueBinder;\nuse Maatwebsite\\Excel\\Concerns\\WithEvents;\nuse Maatwebsite\\Excel\\Concerns\\WithFormatData;\nuse Maatwebsite\\Excel\\Concerns\\WithMultipleSheets;\nuse Maatwebsite\\Excel\\Events\\AfterImport;\nuse Maatwebsite\\Excel\\Events\\BeforeImport;\nuse Maatwebsite\\Excel\\Events\\ImportFailed;\nuse Maatwebsite\\Excel\\Exceptions\\NoTypeDetectedException;\nuse Maatwebsite\\Excel\\Exceptions\\SheetNotFoundException;\nuse Maatwebsite\\Excel\\Factories\\ReaderFactory;\nuse Maatwebsite\\Excel\\Files\\TemporaryFile;\nuse Maatwebsite\\Excel\\Files\\TemporaryFileFactory;\nuse Maatwebsite\\Excel\\Transactions\\TransactionHandler;\nuse PhpOffice\\PhpSpreadsheet\\Cell\\Cell;\nuse PhpOffice\\PhpSpreadsheet\\Reader\\Exception;\nuse PhpOffice\\PhpSpreadsheet\\Reader\\IReader;\nuse PhpOffice\\PhpSpreadsheet\\Spreadsheet;\nuse Symfony\\Component\\HttpFoundation\\File\\UploadedFile;\nuse Throwable;\n\n/** @mixin Spreadsheet */\nclass Reader\n{\n    use DelegatedMacroable, HasEventBus;\n\n    /**\n     * @var Spreadsheet\n     */\n    protected $spreadsheet;\n\n    /**\n     * @var object[]\n     */\n    protected $sheetImports = [];\n\n    /**\n     * @var TemporaryFile\n     */\n    protected $currentFile;\n\n    /**\n     * @var TemporaryFileFactory\n     */\n    protected $temporaryFileFactory;\n\n    /**\n     * @var TransactionHandler\n     */\n    protected $transaction;\n\n    /**\n     * @var IReader\n     */\n    protected $reader;\n\n    /**\n     * @param  TemporaryFileFactory  $temporaryFileFactory\n     * @param  TransactionHandler  $transaction\n     */\n    public function __construct(TemporaryFileFactory $temporaryFileFactory, TransactionHandler $transaction)\n    {\n        $this->setDefaultValueBinder();\n\n        $this->transaction          = $transaction;\n        $this->temporaryFileFactory = $temporaryFileFactory;\n    }\n\n    public function __sleep()\n    {\n        return ['spreadsheet', 'sheetImports', 'currentFile', 'temporaryFileFactory', 'reader'];\n    }\n\n    public function __wakeup()\n    {\n        $this->transaction = app(TransactionHandler::class);\n    }\n\n    /**\n     * @param  object  $import\n     * @param  string|UploadedFile  $filePath\n     * @param  string|null  $readerType\n     * @param  string|null  $disk\n     * @return \\Illuminate\\Foundation\\Bus\\PendingDispatch|$this\n     *\n     * @throws NoTypeDetectedException\n     * @throws \\Illuminate\\Contracts\\Filesystem\\FileNotFoundException\n     * @throws Exception\n     */\n    public function read($import, $filePath, ?string $readerType = null, ?string $disk = null)\n    {\n        $this->reader = $this->getReader($import, $filePath, $readerType, $disk);\n\n        if ($import instanceof WithChunkReading) {\n            return app(ChunkReader::class)->read($import, $this, $this->currentFile);\n        }\n\n        try {\n            $this->loadSpreadsheet($import);\n\n            ($this->transaction)(function () use ($import) {\n                $sheetsToDisconnect = [];\n\n                foreach ($this->sheetImports as $index => $sheetImport) {\n                    if ($sheet = $this->getSheet($import, $sheetImport, $index)) {\n                        $sheet->import($sheetImport, $sheet->getStartRow($sheetImport));\n\n                        // when using WithCalculatedFormulas we need to keep the sheet until all sheets are imported\n                        if (!($sheetImport instanceof HasReferencesToOtherSheets)) {\n                            $sheet->disconnect();\n                        } else {\n                            $sheetsToDisconnect[] = $sheet;\n                        }\n                    }\n                }\n\n                foreach ($sheetsToDisconnect as $sheet) {\n                    $sheet->disconnect();\n                }\n            });\n\n            $this->afterImport($import);\n        } catch (Throwable $e) {\n            $this->raise(new ImportFailed($e));\n            $this->garbageCollect();\n            throw $e;\n        }\n\n        return $this;\n    }\n\n    /**\n     * @param  object  $import\n     * @param  string|UploadedFile  $filePath\n     * @param  string  $readerType\n     * @param  string|null  $disk\n     * @return array\n     *\n     * @throws \\Illuminate\\Contracts\\Filesystem\\FileNotFoundException\n     * @throws \\PhpOffice\\PhpSpreadsheet\\Exception\n     * @throws NoTypeDetectedException\n     * @throws Exceptions\\SheetNotFoundException\n     */\n    public function toArray($import, $filePath, ?string $readerType = null, ?string $disk = null): array\n    {\n        $this->reader = $this->getReader($import, $filePath, $readerType, $disk);\n\n        $this->loadSpreadsheet($import);\n\n        $sheets             = [];\n        $sheetsToDisconnect = [];\n        foreach ($this->sheetImports as $index => $sheetImport) {\n            $calculatesFormulas = $sheetImport instanceof WithCalculatedFormulas;\n            $formatData         = $sheetImport instanceof WithFormatData;\n            if ($sheet = $this->getSheet($import, $sheetImport, $index)) {\n                $sheets[$index] = $sheet->toArray($sheetImport, $sheet->getStartRow($sheetImport), null, $calculatesFormulas, $formatData);\n\n                // when using WithCalculatedFormulas we need to keep the sheet until all sheets are imported\n                if (!($sheetImport instanceof HasReferencesToOtherSheets)) {\n                    $sheet->disconnect();\n                } else {\n                    $sheetsToDisconnect[] = $sheet;\n                }\n            }\n        }\n\n        foreach ($sheetsToDisconnect as $sheet) {\n            $sheet->disconnect();\n        }\n\n        $this->afterImport($import);\n\n        return $sheets;\n    }\n\n    /**\n     * @param  object  $import\n     * @param  string|UploadedFile  $filePath\n     * @param  string  $readerType\n     * @param  string|null  $disk\n     * @return Collection\n     *\n     * @throws \\Illuminate\\Contracts\\Filesystem\\FileNotFoundException\n     * @throws \\PhpOffice\\PhpSpreadsheet\\Exception\n     * @throws NoTypeDetectedException\n     * @throws Exceptions\\SheetNotFoundException\n     */\n    public function toCollection($import, $filePath, ?string $readerType = null, ?string $disk = null): Collection\n    {\n        $this->reader = $this->getReader($import, $filePath, $readerType, $disk);\n        $this->loadSpreadsheet($import);\n\n        $sheets             = new Collection();\n        $sheetsToDisconnect = [];\n        foreach ($this->sheetImports as $index => $sheetImport) {\n            $calculatesFormulas = $sheetImport instanceof WithCalculatedFormulas;\n            $formatData         = $sheetImport instanceof WithFormatData;\n            if ($sheet = $this->getSheet($import, $sheetImport, $index)) {\n                $sheets->put($index, $sheet->toCollection($sheetImport, $sheet->getStartRow($sheetImport), null, $calculatesFormulas, $formatData));\n\n                // when using WithCalculatedFormulas we need to keep the sheet until all sheets are imported\n                if (!($sheetImport instanceof HasReferencesToOtherSheets)) {\n                    $sheet->disconnect();\n                } else {\n                    $sheetsToDisconnect[] = $sheet;\n                }\n            }\n        }\n\n        foreach ($sheetsToDisconnect as $sheet) {\n            $sheet->disconnect();\n        }\n\n        $this->afterImport($import);\n\n        return $sheets;\n    }\n\n    /**\n     * @return Spreadsheet\n     */\n    public function getDelegate()\n    {\n        return $this->spreadsheet;\n    }\n\n    /**\n     * @return $this\n     */\n    public function setDefaultValueBinder(): self\n    {\n        Cell::setValueBinder(\n            app(config('excel.value_binder.default', DefaultValueBinder::class))\n        );\n\n        return $this;\n    }\n\n    /**\n     * @param  object  $import\n     */\n    public function loadSpreadsheet($import)\n    {\n        $this->sheetImports = $this->buildSheetImports($import);\n\n        $this->readSpreadsheet();\n\n        // When no multiple sheets, use the main import object\n        // for each loaded sheet in the spreadsheet\n        if (!$import instanceof WithMultipleSheets) {\n            $this->sheetImports = array_fill(0, $this->spreadsheet->getSheetCount(), $import);\n        }\n\n        $this->beforeImport($import);\n    }\n\n    public function readSpreadsheet()\n    {\n        $this->spreadsheet = $this->reader->load(\n            $this->currentFile->getLocalPath()\n        );\n    }\n\n    /**\n     * @param  object  $import\n     */\n    public function beforeImport($import)\n    {\n        $this->raise(new BeforeImport($this, $import));\n    }\n\n    /**\n     * @param  object  $import\n     */\n    public function afterImport($import)\n    {\n        $this->raise(new AfterImport($this, $import));\n\n        $this->garbageCollect();\n    }\n\n    /**\n     * @return IReader\n     */\n    public function getPhpSpreadsheetReader(): IReader\n    {\n        return $this->reader;\n    }\n\n    /**\n     * @param  object  $import\n     * @return array\n     */\n    public function getWorksheets($import): array\n    {\n        // Csv doesn't have worksheets.\n        if (!method_exists($this->reader, 'listWorksheetNames')) {\n            return ['Worksheet' => $import];\n        }\n\n        $worksheets     = [];\n        $worksheetNames = $this->reader->listWorksheetNames($this->currentFile->getLocalPath());\n        if ($import instanceof WithMultipleSheets) {\n            $sheetImports = $import->sheets();\n\n            foreach ($sheetImports as $index => $sheetImport) {\n                // Translate index to name.\n                if (is_numeric($index)) {\n                    $index = $worksheetNames[$index] ?? $index;\n                }\n\n                // Specify with worksheet name should have which import.\n                $worksheets[$index] = $sheetImport;\n            }\n\n            // Load specific sheets.\n            if (method_exists($this->reader, 'setLoadSheetsOnly')) {\n                $this->reader->setLoadSheetsOnly(\n                    collect($worksheetNames)->intersect(array_keys($worksheets))->values()->all()\n                );\n            }\n        } else {\n            // Each worksheet the same import class.\n            foreach ($worksheetNames as $name) {\n                $worksheets[$name] = $import;\n            }\n        }\n\n        return $worksheets;\n    }\n\n    /**\n     * @return array\n     */\n    public function getTotalRows(): array\n    {\n        $info = $this->reader->listWorksheetInfo($this->currentFile->getLocalPath());\n\n        $totalRows = [];\n        foreach ($info as $sheet) {\n            $totalRows[$sheet['worksheetName']] = $sheet['totalRows'];\n        }\n\n        return $totalRows;\n    }\n\n    /**\n     * @param  $import\n     * @param  $sheetImport\n     * @param  $index\n     * @return Sheet|null\n     *\n     * @throws \\PhpOffice\\PhpSpreadsheet\\Exception\n     * @throws SheetNotFoundException\n     */\n    protected function getSheet($import, $sheetImport, $index)\n    {\n        try {\n            return Sheet::make($this->spreadsheet, $index);\n        } catch (SheetNotFoundException $e) {\n            if ($import instanceof SkipsUnknownSheets) {\n                $import->onUnknownSheet($index);\n\n                return null;\n            }\n\n            if ($sheetImport instanceof SkipsUnknownSheets) {\n                $sheetImport->onUnknownSheet($index);\n\n                return null;\n            }\n\n            throw $e;\n        }\n    }\n\n    /**\n     * @param  object  $import\n     * @return array\n     */\n    private function buildSheetImports($import): array\n    {\n        $sheetImports = [];\n        if ($import instanceof WithMultipleSheets) {\n            $sheetImports = $import->sheets();\n\n            // When only sheet names are given and the reader has\n            // an option to load only the selected sheets.\n            if (\n                method_exists($this->reader, 'setLoadSheetsOnly')\n                && count(array_filter(array_keys($sheetImports), 'is_numeric')) === 0\n            ) {\n                $this->reader->setLoadSheetsOnly(array_keys($sheetImports));\n            }\n        }\n\n        return $sheetImports;\n    }\n\n    /**\n     * @param  object  $import\n     * @param  string|UploadedFile  $filePath\n     * @param  string|null  $readerType\n     * @param  string  $disk\n     * @return IReader\n     *\n     * @throws \\Illuminate\\Contracts\\Filesystem\\FileNotFoundException\n     * @throws NoTypeDetectedException\n     * @throws \\PhpOffice\\PhpSpreadsheet\\Reader\\Exception\n     * @throws InvalidArgumentException\n     */\n    private function getReader($import, $filePath, ?string $readerType = null, ?string $disk = null): IReader\n    {\n        $shouldQueue = $import instanceof ShouldQueue;\n        if ($shouldQueue && !$import instanceof WithChunkReading) {\n            throw new InvalidArgumentException('ShouldQueue is only supported in combination with WithChunkReading.');\n        }\n\n        if ($import instanceof WithEvents) {\n            $this->registerListeners($import->registerEvents());\n        }\n\n        if ($import instanceof WithCustomValueBinder) {\n            Cell::setValueBinder($import);\n        }\n\n        $fileExtension     = pathinfo($filePath, PATHINFO_EXTENSION);\n        $temporaryFile     = $shouldQueue ? $this->temporaryFileFactory->make($fileExtension) : $this->temporaryFileFactory->makeLocal(null, $fileExtension);\n        $this->currentFile = $temporaryFile->copyFrom(\n            $filePath,\n            $disk\n        );\n\n        return ReaderFactory::make(\n            $import,\n            $this->currentFile,\n            $readerType\n        );\n    }\n\n    /**\n     * Garbage collect.\n     */\n    private function garbageCollect()\n    {\n        $this->clearListeners();\n        $this->setDefaultValueBinder();\n\n        // Force garbage collecting\n        unset($this->sheetImports, $this->spreadsheet);\n\n        $this->currentFile->delete();\n    }\n}\n"
  },
  {
    "path": "src/RegistersCustomConcerns.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel;\n\nuse Maatwebsite\\Excel\\Events\\AfterSheet;\nuse Maatwebsite\\Excel\\Events\\BeforeExport;\nuse Maatwebsite\\Excel\\Events\\BeforeSheet;\nuse Maatwebsite\\Excel\\Events\\BeforeWriting;\nuse Maatwebsite\\Excel\\Events\\Event;\n\ntrait RegistersCustomConcerns\n{\n    /**\n     * @var array\n     */\n    private static $eventMap = [\n        BeforeWriting::class => Writer::class,\n        BeforeExport::class  => Writer::class,\n        BeforeSheet::class   => Sheet::class,\n        AfterSheet::class    => Sheet::class,\n    ];\n\n    /**\n     * @param  string  $concern\n     * @param  callable  $handler\n     * @param  string  $event\n     */\n    public static function extend(string $concern, callable $handler, string $event = BeforeWriting::class)\n    {\n        /** @var HasEventBus $delegate */\n        $delegate = static::$eventMap[$event] ?? BeforeWriting::class;\n\n        $delegate::listen($event, function (Event $event) use ($concern, $handler) {\n            if ($event->appliesToConcern($concern)) {\n                $handler($event->getConcernable(), $event->getDelegate());\n            }\n        });\n    }\n}\n"
  },
  {
    "path": "src/Row.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel;\n\nuse ArrayAccess;\nuse Closure;\nuse Illuminate\\Support\\Collection;\nuse PhpOffice\\PhpSpreadsheet\\Worksheet\\Row as SpreadsheetRow;\n\n/** @mixin SpreadsheetRow */\nclass Row implements ArrayAccess\n{\n    use DelegatedMacroable;\n\n    /**\n     * @var array\n     */\n    protected $headingRow = [];\n\n    /**\n     * @var array\n     */\n    protected $headerIsGrouped = [];\n\n    /**\n     * @var \\Closure\n     */\n    protected $preparationCallback;\n\n    /**\n     * @var SpreadsheetRow\n     */\n    protected $row;\n\n    /**\n     * @var array|null\n     */\n    protected $rowCache;\n\n    /**\n     * @var bool|null\n     */\n    protected $rowCacheFormatData;\n\n    /**\n     * @var string|null\n     */\n    protected $rowCacheEndColumn;\n\n    /**\n     * @param  SpreadsheetRow  $row\n     * @param  array  $headingRow\n     * @param  array  $headerIsGrouped\n     */\n    public function __construct(SpreadsheetRow $row, array $headingRow = [], array $headerIsGrouped = [])\n    {\n        $this->row             = $row;\n        $this->headingRow      = $headingRow;\n        $this->headerIsGrouped = $headerIsGrouped;\n    }\n\n    /**\n     * @return SpreadsheetRow\n     */\n    public function getDelegate(): SpreadsheetRow\n    {\n        return $this->row;\n    }\n\n    /**\n     * @param  null  $nullValue\n     * @param  bool  $calculateFormulas\n     * @param  bool  $formatData\n     * @param  string|null  $endColumn\n     * @return Collection\n     */\n    public function toCollection($nullValue = null, $calculateFormulas = false, $formatData = true, ?string $endColumn = null): Collection\n    {\n        return new Collection($this->toArray($nullValue, $calculateFormulas, $formatData, $endColumn));\n    }\n\n    /**\n     * @param  null  $nullValue\n     * @param  bool  $calculateFormulas\n     * @param  bool  $formatData\n     * @param  string|null  $endColumn\n     * @return array\n     */\n    public function toArray($nullValue = null, $calculateFormulas = false, $formatData = true, ?string $endColumn = null)\n    {\n        if (is_array($this->rowCache) && ($this->rowCacheFormatData === $formatData) && ($this->rowCacheEndColumn === $endColumn)) {\n            return $this->rowCache;\n        }\n\n        $cells = [];\n\n        $i = 0;\n        foreach ($this->row->getCellIterator('A', $endColumn) as $cell) {\n            $value = (new Cell($cell))->getValue($nullValue, $calculateFormulas, $formatData);\n\n            if (isset($this->headingRow[$i])) {\n                if (!$this->headerIsGrouped[$i]) {\n                    $cells[$this->headingRow[$i]] = $value;\n                } else {\n                    $cells[$this->headingRow[$i]][] = $value;\n                }\n            } else {\n                $cells[] = $value;\n            }\n\n            $i++;\n        }\n\n        if (isset($this->preparationCallback)) {\n            $cells = ($this->preparationCallback)($cells, $this->row->getRowIndex());\n        }\n\n        $this->rowCache           = $cells;\n        $this->rowCacheFormatData = $formatData;\n        $this->rowCacheEndColumn  = $endColumn;\n\n        return $cells;\n    }\n\n    /**\n     * @param  bool  $calculateFormulas\n     * @param  string|null  $endColumn\n     * @return bool\n     */\n    public function isEmpty($calculateFormulas = false, ?string $endColumn = null): bool\n    {\n        return count(array_filter($this->toArray(null, $calculateFormulas, false, $endColumn))) === 0;\n    }\n\n    /**\n     * @return int\n     */\n    public function getIndex(): int\n    {\n        return $this->row->getRowIndex();\n    }\n\n    #[\\ReturnTypeWillChange]\n    public function offsetExists($offset)\n    {\n        return isset($this->toArray()[$offset]);\n    }\n\n    #[\\ReturnTypeWillChange]\n    public function offsetGet($offset)\n    {\n        return $this->toArray()[$offset];\n    }\n\n    #[\\ReturnTypeWillChange]\n    public function offsetSet($offset, $value)\n    {\n        //\n    }\n\n    #[\\ReturnTypeWillChange]\n    public function offsetUnset($offset)\n    {\n        //\n    }\n\n    /**\n     * @param  \\Closure  $preparationCallback\n     *\n     * @internal\n     */\n    public function setPreparationCallback(?Closure $preparationCallback = null)\n    {\n        $this->preparationCallback = $preparationCallback;\n    }\n}\n"
  },
  {
    "path": "src/SettingsProvider.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel;\n\nuse Maatwebsite\\Excel\\Cache\\CacheManager;\nuse PhpOffice\\PhpSpreadsheet\\Settings;\n\nclass SettingsProvider\n{\n    /**\n     * @var CacheManager\n     */\n    private $cache;\n\n    public function __construct(CacheManager $cache)\n    {\n        $this->cache = $cache;\n    }\n\n    /**\n     * Provide PhpSpreadsheet settings.\n     */\n    public function provide()\n    {\n        $this->configureCellCaching();\n    }\n\n    protected function configureCellCaching()\n    {\n        Settings::setCache(\n            $this->cache->driver()\n        );\n    }\n}\n"
  },
  {
    "path": "src/Sheet.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel;\n\nuse Closure;\nuse Illuminate\\Contracts\\Support\\Arrayable;\nuse Illuminate\\Support\\Collection;\nuse Illuminate\\Support\\LazyCollection;\nuse Maatwebsite\\Excel\\Concerns\\FromArray;\nuse Maatwebsite\\Excel\\Concerns\\FromCollection;\nuse Maatwebsite\\Excel\\Concerns\\FromGenerator;\nuse Maatwebsite\\Excel\\Concerns\\FromIterator;\nuse Maatwebsite\\Excel\\Concerns\\FromQuery;\nuse Maatwebsite\\Excel\\Concerns\\FromView;\nuse Maatwebsite\\Excel\\Concerns\\OnEachRow;\nuse Maatwebsite\\Excel\\Concerns\\ShouldAutoSize;\nuse Maatwebsite\\Excel\\Concerns\\SkipsEmptyRows;\nuse Maatwebsite\\Excel\\Concerns\\SkipsOnError;\nuse Maatwebsite\\Excel\\Concerns\\ToArray;\nuse Maatwebsite\\Excel\\Concerns\\ToCollection;\nuse Maatwebsite\\Excel\\Concerns\\ToModel;\nuse Maatwebsite\\Excel\\Concerns\\WithCalculatedFormulas;\nuse Maatwebsite\\Excel\\Concerns\\WithCharts;\nuse Maatwebsite\\Excel\\Concerns\\WithChunkReading;\nuse Maatwebsite\\Excel\\Concerns\\WithColumnFormatting;\nuse Maatwebsite\\Excel\\Concerns\\WithColumnLimit;\nuse Maatwebsite\\Excel\\Concerns\\WithColumnWidths;\nuse Maatwebsite\\Excel\\Concerns\\WithCustomChunkSize;\nuse Maatwebsite\\Excel\\Concerns\\WithCustomStartCell;\nuse Maatwebsite\\Excel\\Concerns\\WithCustomValueBinder;\nuse Maatwebsite\\Excel\\Concerns\\WithDrawings;\nuse Maatwebsite\\Excel\\Concerns\\WithEvents;\nuse Maatwebsite\\Excel\\Concerns\\WithFormatData;\nuse Maatwebsite\\Excel\\Concerns\\WithHeadings;\nuse Maatwebsite\\Excel\\Concerns\\WithMappedCells;\nuse Maatwebsite\\Excel\\Concerns\\WithMapping;\nuse Maatwebsite\\Excel\\Concerns\\WithProgressBar;\nuse Maatwebsite\\Excel\\Concerns\\WithStrictNullComparison;\nuse Maatwebsite\\Excel\\Concerns\\WithStyles;\nuse Maatwebsite\\Excel\\Concerns\\WithTitle;\nuse Maatwebsite\\Excel\\Concerns\\WithValidation;\nuse Maatwebsite\\Excel\\Events\\AfterSheet;\nuse Maatwebsite\\Excel\\Events\\BeforeSheet;\nuse Maatwebsite\\Excel\\Exceptions\\ConcernConflictException;\nuse Maatwebsite\\Excel\\Exceptions\\RowSkippedException;\nuse Maatwebsite\\Excel\\Exceptions\\SheetNotFoundException;\nuse Maatwebsite\\Excel\\Files\\TemporaryFileFactory;\nuse Maatwebsite\\Excel\\Helpers\\ArrayHelper;\nuse Maatwebsite\\Excel\\Helpers\\CellHelper;\nuse Maatwebsite\\Excel\\Imports\\EndRowFinder;\nuse Maatwebsite\\Excel\\Imports\\HeadingRowExtractor;\nuse Maatwebsite\\Excel\\Imports\\ModelImporter;\nuse Maatwebsite\\Excel\\Validators\\RowValidator;\nuse PhpOffice\\PhpSpreadsheet\\Cell\\Cell as SpreadsheetCell;\nuse PhpOffice\\PhpSpreadsheet\\Chart\\Chart;\nuse PhpOffice\\PhpSpreadsheet\\IOFactory;\nuse PhpOffice\\PhpSpreadsheet\\Reader\\Html;\nuse PhpOffice\\PhpSpreadsheet\\Shared\\StringHelper;\nuse PhpOffice\\PhpSpreadsheet\\Spreadsheet;\nuse PhpOffice\\PhpSpreadsheet\\Worksheet\\BaseDrawing;\nuse PhpOffice\\PhpSpreadsheet\\Worksheet\\Worksheet;\nuse Throwable;\n\n/** @mixin Worksheet */\nclass Sheet\n{\n    use DelegatedMacroable, HasEventBus;\n\n    /**\n     * @var int\n     */\n    protected $chunkSize;\n\n    /**\n     * @var TemporaryFileFactory\n     */\n    protected $temporaryFileFactory;\n\n    /**\n     * @var object\n     */\n    protected $exportable;\n\n    /**\n     * @var Worksheet\n     */\n    private $worksheet;\n\n    /**\n     * @param  Worksheet  $worksheet\n     */\n    public function __construct(Worksheet $worksheet)\n    {\n        $this->worksheet            = $worksheet;\n        $this->chunkSize            = config('excel.exports.chunk_size', 100);\n        $this->temporaryFileFactory = app(TemporaryFileFactory::class);\n    }\n\n    /**\n     * @param  Spreadsheet  $spreadsheet\n     * @param  string|int  $index\n     * @return Sheet\n     *\n     * @throws \\PhpOffice\\PhpSpreadsheet\\Exception\n     * @throws SheetNotFoundException\n     */\n    public static function make(Spreadsheet $spreadsheet, $index)\n    {\n        if (is_numeric($index)) {\n            return self::byIndex($spreadsheet, $index);\n        }\n\n        return self::byName($spreadsheet, $index);\n    }\n\n    /**\n     * @param  Spreadsheet  $spreadsheet\n     * @param  int  $index\n     * @return Sheet\n     *\n     * @throws \\PhpOffice\\PhpSpreadsheet\\Exception\n     * @throws SheetNotFoundException\n     */\n    public static function byIndex(Spreadsheet $spreadsheet, int $index): Sheet\n    {\n        if (!isset($spreadsheet->getAllSheets()[$index])) {\n            throw SheetNotFoundException::byIndex($index, $spreadsheet->getSheetCount());\n        }\n\n        return new static($spreadsheet->getSheet($index));\n    }\n\n    /**\n     * @param  Spreadsheet  $spreadsheet\n     * @param  string  $name\n     * @return Sheet\n     *\n     * @throws SheetNotFoundException\n     */\n    public static function byName(Spreadsheet $spreadsheet, string $name): Sheet\n    {\n        if (!$spreadsheet->sheetNameExists($name)) {\n            throw SheetNotFoundException::byName($name);\n        }\n\n        return new static($spreadsheet->getSheetByName($name));\n    }\n\n    /**\n     * @param  object  $sheetExport\n     *\n     * @throws \\PhpOffice\\PhpSpreadsheet\\Exception\n     */\n    public function open($sheetExport)\n    {\n        $this->exportable = $sheetExport;\n\n        if ($sheetExport instanceof WithCustomValueBinder) {\n            SpreadsheetCell::setValueBinder($sheetExport);\n        }\n\n        if ($sheetExport instanceof WithEvents) {\n            $this->registerListeners($sheetExport->registerEvents());\n        }\n\n        $this->raise(new BeforeSheet($this, $this->exportable));\n\n        if ($sheetExport instanceof WithTitle) {\n            $title = $sheetExport->title();\n\n            $title = str_replace(['*', ':', '/', '\\\\', '?', '[', ']'], '', $title);\n            if (StringHelper::countCharacters($title) > Worksheet::SHEET_TITLE_MAXIMUM_LENGTH) {\n                $title = StringHelper::substring($title, 0, Worksheet::SHEET_TITLE_MAXIMUM_LENGTH);\n            }\n\n            $this->worksheet->setTitle($title);\n        }\n\n        if (($sheetExport instanceof FromQuery || $sheetExport instanceof FromCollection || $sheetExport instanceof FromArray) && $sheetExport instanceof FromView) {\n            throw ConcernConflictException::queryOrCollectionAndView();\n        }\n\n        if (!$sheetExport instanceof FromView && $sheetExport instanceof WithHeadings) {\n            if ($sheetExport instanceof WithCustomStartCell) {\n                $startCell = $sheetExport->startCell();\n            }\n\n            $this->append(\n                ArrayHelper::ensureMultipleRows($sheetExport->headings()),\n                $startCell ?? null,\n                $this->hasStrictNullComparison($sheetExport)\n            );\n        }\n    }\n\n    /**\n     * @param  object  $sheetExport\n     *\n     * @throws \\PhpOffice\\PhpSpreadsheet\\Exception\n     * @throws \\PhpOffice\\PhpSpreadsheet\\Reader\\Exception\n     */\n    public function export($sheetExport)\n    {\n        $this->open($sheetExport);\n\n        if ($sheetExport instanceof FromView) {\n            $this->fromView($sheetExport);\n        } else {\n            if ($sheetExport instanceof FromQuery) {\n                $this->fromQuery($sheetExport, $this->worksheet);\n            }\n\n            if ($sheetExport instanceof FromCollection) {\n                $this->fromCollection($sheetExport);\n            }\n\n            if ($sheetExport instanceof FromArray) {\n                $this->fromArray($sheetExport);\n            }\n\n            if ($sheetExport instanceof FromIterator) {\n                $this->fromIterator($sheetExport);\n            }\n\n            if ($sheetExport instanceof FromGenerator) {\n                $this->fromGenerator($sheetExport);\n            }\n        }\n\n        $this->close($sheetExport);\n    }\n\n    /**\n     * @param  object  $import\n     * @param  int  $startRow\n     */\n    public function import($import, int $startRow = 1)\n    {\n        if ($import instanceof WithEvents) {\n            $this->registerListeners($import->registerEvents());\n        }\n\n        $this->raise(new BeforeSheet($this, $import));\n\n        if ($import instanceof WithProgressBar && !$import instanceof WithChunkReading) {\n            $import->getConsoleOutput()->progressStart($this->worksheet->getHighestRow());\n        }\n\n        $calculatesFormulas = $import instanceof WithCalculatedFormulas;\n        $formatData         = $import instanceof WithFormatData;\n\n        if ($import instanceof WithMappedCells) {\n            app(MappedReader::class)->map($import, $this->worksheet);\n        } else {\n            if ($import instanceof ToModel) {\n                app(ModelImporter::class)->import($this->worksheet, $import, $startRow);\n            }\n\n            if ($import instanceof ToCollection) {\n                $rows = $this->toCollection($import, $startRow, null, $calculatesFormulas, $formatData);\n\n                if ($import instanceof WithValidation) {\n                    $rows = $this->validated($import, $startRow, $rows);\n                }\n\n                $import->collection($rows);\n            }\n\n            if ($import instanceof ToArray) {\n                $rows = $this->toArray($import, $startRow, null, $calculatesFormulas, $formatData);\n\n                if ($import instanceof WithValidation) {\n                    $rows = $this->validated($import, $startRow, $rows);\n                }\n\n                $import->array($rows);\n            }\n        }\n\n        if ($import instanceof OnEachRow) {\n            $headingRow          = HeadingRowExtractor::extract($this->worksheet, $import);\n            $headerIsGrouped     = HeadingRowExtractor::extractGrouping($headingRow, $import);\n            $endColumn           = $import instanceof WithColumnLimit ? $import->endColumn() : null;\n            $preparationCallback = $this->getPreparationCallback($import);\n\n            foreach ($this->worksheet->getRowIterator()->resetStart($startRow ?? 1) as $row) {\n                $sheetRow = new Row($row, $headingRow, $headerIsGrouped);\n\n                if ($import instanceof WithValidation) {\n                    $sheetRow->setPreparationCallback($preparationCallback);\n                }\n\n                $rowArray                    = $sheetRow->toArray(null, $import instanceof WithCalculatedFormulas, $import instanceof WithFormatData, $endColumn);\n                $rowIsEmptyAccordingToImport = $import instanceof SkipsEmptyRows && method_exists($import, 'isEmptyWhen') && $import->isEmptyWhen($rowArray);\n                if (!$import instanceof SkipsEmptyRows || ($import instanceof SkipsEmptyRows && (!$rowIsEmptyAccordingToImport && !$sheetRow->isEmpty($calculatesFormulas)))) {\n                    if ($import instanceof WithValidation) {\n                        $toValidate = [$sheetRow->getIndex() => $rowArray];\n\n                        try {\n                            app(RowValidator::class)->validate($toValidate, $import);\n                            $import->onRow($sheetRow);\n                        } catch (RowSkippedException $e) {\n                        } catch (Throwable $e) {\n                            if ($import instanceof SkipsOnError) {\n                                $import->onError($e);\n                            } else {\n                                throw $e;\n                            }\n                        }\n                    } else {\n                        try {\n                            $import->onRow($sheetRow);\n                        } catch (Throwable $e) {\n                            if ($import instanceof SkipsOnError) {\n                                $import->onError($e);\n                            } else {\n                                throw $e;\n                            }\n                        }\n                    }\n                }\n\n                if ($import instanceof WithProgressBar) {\n                    $import->getConsoleOutput()->progressAdvance();\n                }\n            }\n        }\n\n        $this->raise(new AfterSheet($this, $import));\n\n        if ($import instanceof WithProgressBar && !$import instanceof WithChunkReading) {\n            $import->getConsoleOutput()->progressFinish();\n        }\n    }\n\n    /**\n     * @param  object  $import\n     * @param  int|null  $startRow\n     * @param  null  $nullValue\n     * @param  bool  $calculateFormulas\n     * @param  bool  $formatData\n     * @return array\n     */\n    public function toArray($import, ?int $startRow = null, $nullValue = null, $calculateFormulas = false, $formatData = false)\n    {\n        if ($startRow > $this->worksheet->getHighestRow()) {\n            return [];\n        }\n\n        $endRow          = EndRowFinder::find($import, $startRow, $this->worksheet->getHighestRow());\n        $headingRow      = HeadingRowExtractor::extract($this->worksheet, $import);\n        $headerIsGrouped = HeadingRowExtractor::extractGrouping($headingRow, $import);\n        $endColumn       = $import instanceof WithColumnLimit ? $import->endColumn() : null;\n\n        $rows = [];\n        foreach ($this->worksheet->getRowIterator($startRow, $endRow) as $index => $row) {\n            $row = new Row($row, $headingRow, $headerIsGrouped);\n\n            if ($import instanceof SkipsEmptyRows && $row->isEmpty($calculateFormulas, $endColumn)) {\n                continue;\n            }\n\n            $row = $row->toArray($nullValue, $calculateFormulas, $formatData, $endColumn);\n\n            if ($import && method_exists($import, 'isEmptyWhen') && $import->isEmptyWhen($row)) {\n                continue;\n            }\n\n            if ($import instanceof WithMapping) {\n                $row = $import->map($row);\n            }\n\n            if ($import instanceof WithValidation && method_exists($import, 'prepareForValidation')) {\n                $row = $import->prepareForValidation($row, $index);\n            }\n\n            $rows[] = $row;\n\n            if ($import instanceof WithProgressBar) {\n                $import->getConsoleOutput()->progressAdvance();\n            }\n        }\n\n        return $rows;\n    }\n\n    /**\n     * @param  object  $import\n     * @param  int|null  $startRow\n     * @param  null  $nullValue\n     * @param  bool  $calculateFormulas\n     * @param  bool  $formatData\n     * @return Collection\n     */\n    public function toCollection($import, ?int $startRow = null, $nullValue = null, $calculateFormulas = false, $formatData = false): Collection\n    {\n        $rows = $this->toArray($import, $startRow, $nullValue, $calculateFormulas, $formatData);\n\n        return new Collection(array_map(function (array $row) {\n            return new Collection($row);\n        }, $rows));\n    }\n\n    /**\n     * @param  object  $sheetExport\n     *\n     * @throws \\PhpOffice\\PhpSpreadsheet\\Exception\n     */\n    public function close($sheetExport)\n    {\n        if ($sheetExport instanceof WithCharts) {\n            $this->addCharts($sheetExport->charts());\n        }\n\n        if ($sheetExport instanceof WithDrawings) {\n            $this->addDrawings($sheetExport->drawings());\n        }\n\n        $this->exportable = $sheetExport;\n\n        if ($sheetExport instanceof WithColumnFormatting) {\n            foreach ($sheetExport->columnFormats() as $column => $format) {\n                $this->formatColumn($column, $format);\n            }\n        }\n\n        if ($sheetExport instanceof ShouldAutoSize) {\n            $this->autoSize();\n        }\n\n        if ($sheetExport instanceof WithColumnWidths) {\n            foreach ($sheetExport->columnWidths() as $column => $width) {\n                $this->worksheet->getColumnDimension($column)->setAutoSize(false)->setWidth($width);\n            }\n        }\n\n        if ($sheetExport instanceof WithStyles) {\n            $styles = $sheetExport->styles($this->worksheet);\n            if (is_array($styles)) {\n                foreach ($styles as $coordinate => $coordinateStyles) {\n                    if (is_numeric($coordinate)) {\n                        $coordinate = 'A' . $coordinate . ':' . $this->worksheet->getHighestColumn($coordinate) . $coordinate;\n                    }\n\n                    $this->worksheet->getStyle($coordinate)->applyFromArray($coordinateStyles);\n                }\n            }\n        }\n\n        $this->raise(new AfterSheet($this, $this->exportable));\n\n        $this->clearListeners();\n    }\n\n    /**\n     * @param  FromView  $sheetExport\n     * @param  int|null  $sheetIndex\n     *\n     * @throws \\PhpOffice\\PhpSpreadsheet\\Reader\\Exception\n     */\n    public function fromView(FromView $sheetExport, $sheetIndex = null)\n    {\n        $temporaryFile = $this->temporaryFileFactory->makeLocal(null, 'html');\n        $temporaryFile->put($sheetExport->view()->render());\n\n        $spreadsheet = $this->worksheet->getParent();\n\n        /** @var Html $reader */\n        $reader = IOFactory::createReader('Html');\n\n        // If no sheetIndex given, insert content into the last sheet\n        $reader->setSheetIndex($sheetIndex ?? $spreadsheet->getSheetCount() - 1);\n        $reader->loadIntoExisting($temporaryFile->getLocalPath(), $spreadsheet);\n\n        $temporaryFile->delete();\n    }\n\n    /**\n     * @param  FromQuery  $sheetExport\n     * @param  Worksheet  $worksheet\n     */\n    public function fromQuery(FromQuery $sheetExport, Worksheet $worksheet)\n    {\n        $query = $sheetExport->query();\n        if ($query instanceof \\Laravel\\Scout\\Builder) {\n            $this->fromScout($sheetExport, $worksheet);\n\n            return;\n        }\n\n        //Operate on a clone to avoid altering the original\n        //and use the clone operator directly to support old versions of Laravel\n        //that don't have a clone method in eloquent\n        $clonedQuery = clone $query;\n        $clonedQuery->chunk($this->getChunkSize($sheetExport), function ($chunk) use ($sheetExport) {\n            $this->appendRows($chunk, $sheetExport);\n        });\n    }\n\n    /**\n     * @param  FromQuery  $sheetExport\n     * @param  Worksheet  $worksheet\n     */\n    public function fromScout(FromQuery $sheetExport, Worksheet $worksheet)\n    {\n        $scout     = $sheetExport->query();\n        $chunkSize = $this->getChunkSize($sheetExport);\n\n        $chunk = $scout->paginate($chunkSize);\n        // Append first page\n        $this->appendRows($chunk->items(), $sheetExport);\n\n        // Append rest of pages\n        for ($page = 2; $page <= $chunk->lastPage(); $page++) {\n            $this->appendRows($scout->paginate($chunkSize, 'page', $page)->items(), $sheetExport);\n        }\n    }\n\n    /**\n     * @param  FromCollection  $sheetExport\n     */\n    public function fromCollection(FromCollection $sheetExport)\n    {\n        $this->appendRows($sheetExport->collection()->all(), $sheetExport);\n    }\n\n    /**\n     * @param  FromArray  $sheetExport\n     */\n    public function fromArray(FromArray $sheetExport)\n    {\n        $this->appendRows($sheetExport->array(), $sheetExport);\n    }\n\n    /**\n     * @param  FromIterator  $sheetExport\n     */\n    public function fromIterator(FromIterator $sheetExport)\n    {\n        $iterator = class_exists(LazyCollection::class) ? new LazyCollection(function () use ($sheetExport) {\n            foreach ($sheetExport->iterator() as $row) {\n                yield $row;\n            }\n        }) : $sheetExport->iterator();\n\n        $this->appendRows($iterator, $sheetExport);\n    }\n\n    /**\n     * @param  FromGenerator  $sheetExport\n     */\n    public function fromGenerator(FromGenerator $sheetExport)\n    {\n        $generator = class_exists(LazyCollection::class) ? new LazyCollection(function () use ($sheetExport) {\n            foreach ($sheetExport->generator() as $row) {\n                yield $row;\n            }\n        }) : $sheetExport->generator();\n\n        $this->appendRows($generator, $sheetExport);\n    }\n\n    /**\n     * @param  array  $rows\n     * @param  string|null  $startCell\n     * @param  bool  $strictNullComparison\n     */\n    public function append(array $rows, ?string $startCell = null, bool $strictNullComparison = false)\n    {\n        if (!$startCell) {\n            $startCell = 'A1';\n        }\n\n        if ($this->hasRows()) {\n            $startCell = CellHelper::getColumnFromCoordinate($startCell) . ($this->worksheet->getHighestRow() + 1);\n        }\n\n        $this->worksheet->fromArray($rows, null, $startCell, $strictNullComparison);\n    }\n\n    public function autoSize()\n    {\n        foreach ($this->buildColumnRange('A', $this->worksheet->getHighestDataColumn()) as $col) {\n            $dimension = $this->worksheet->getColumnDimension($col);\n\n            // Only auto-size columns that have not have an explicit width.\n            if ($dimension->getWidth() == -1) {\n                $dimension->setAutoSize(true);\n            }\n        }\n    }\n\n    /**\n     * @param  string  $column\n     * @param  string  $format\n     *\n     * @throws \\PhpOffice\\PhpSpreadsheet\\Exception\n     */\n    public function formatColumn(string $column, string $format)\n    {\n        // If the column is a range, we wouldn't need to calculate the range.\n        if (stripos($column, ':') !== false) {\n            $this->worksheet\n                ->getStyle($column)\n                ->getNumberFormat()\n                ->setFormatCode($format);\n        } else {\n            $this->worksheet\n                ->getStyle($column . '1:' . $column . $this->worksheet->getHighestRow())\n                ->getNumberFormat()\n                ->setFormatCode($format);\n        }\n    }\n\n    /**\n     * @param  int  $chunkSize\n     * @return Sheet\n     */\n    public function chunkSize(int $chunkSize)\n    {\n        $this->chunkSize = $chunkSize;\n\n        return $this;\n    }\n\n    /**\n     * @return Worksheet\n     */\n    public function getDelegate()\n    {\n        return $this->worksheet;\n    }\n\n    /**\n     * @param  Chart|Chart[]  $charts\n     */\n    public function addCharts($charts)\n    {\n        $charts = \\is_array($charts) ? $charts : [$charts];\n\n        foreach ($charts as $chart) {\n            $this->worksheet->addChart($chart);\n        }\n    }\n\n    /**\n     * @param  BaseDrawing|BaseDrawing[]  $drawings\n     */\n    public function addDrawings($drawings)\n    {\n        $drawings = \\is_array($drawings) ? $drawings : [$drawings];\n\n        foreach ($drawings as $drawing) {\n            $drawing->setWorksheet($this->worksheet);\n        }\n    }\n\n    /**\n     * @param  string  $concern\n     * @return string\n     */\n    public function hasConcern(string $concern): string\n    {\n        return $this->exportable instanceof $concern;\n    }\n\n    /**\n     * @param  iterable  $rows\n     * @param  object  $sheetExport\n     */\n    public function appendRows($rows, $sheetExport)\n    {\n        if (method_exists($sheetExport, 'prepareRows')) {\n            $rows = $sheetExport->prepareRows($rows);\n        }\n\n        $rows = $rows instanceof LazyCollection ? $rows : new Collection($rows);\n\n        $rows->flatMap(function ($row) use ($sheetExport) {\n            if ($sheetExport instanceof WithMapping) {\n                $row = $sheetExport->map($row);\n            }\n\n            if ($sheetExport instanceof WithCustomValueBinder) {\n                SpreadsheetCell::setValueBinder($sheetExport);\n            }\n\n            return ArrayHelper::ensureMultipleRows(\n                static::mapArraybleRow($row)\n            );\n        })->chunk(1000)->each(function ($rows) use ($sheetExport) {\n            $this->append(\n                $rows->toArray(),\n                $sheetExport instanceof WithCustomStartCell ? $sheetExport->startCell() : null,\n                $this->hasStrictNullComparison($sheetExport)\n            );\n        });\n    }\n\n    /**\n     * @param  mixed  $row\n     * @return array\n     */\n    public static function mapArraybleRow($row): array\n    {\n        // When dealing with eloquent models, we'll skip the relations\n        // as we won't be able to display them anyway.\n        if (is_object($row) && method_exists($row, 'attributesToArray')) {\n            return $row->attributesToArray();\n        }\n\n        if ($row instanceof Arrayable) {\n            return $row->toArray();\n        }\n\n        // Convert StdObjects to arrays\n        if (is_object($row)) {\n            return json_decode(json_encode($row), true);\n        }\n\n        return $row;\n    }\n\n    /**\n     * @param  $sheetImport\n     * @return int\n     */\n    public function getStartRow($sheetImport): int\n    {\n        return HeadingRowExtractor::determineStartRow($sheetImport);\n    }\n\n    /**\n     * Disconnect the sheet.\n     */\n    public function disconnect()\n    {\n        $this->worksheet->disconnectCells();\n        unset($this->worksheet);\n    }\n\n    /**\n     * @return Collection|array\n     */\n    protected function validated(WithValidation $import, int $startRow, $rows)\n    {\n        $toValidate = (new Collection($rows))->mapWithKeys(function ($row, $index) use ($startRow) {\n            return [($startRow + $index) => $row];\n        });\n\n        try {\n            app(RowValidator::class)->validate($toValidate->toArray(), $import);\n        } catch (RowSkippedException $e) {\n            foreach ($e->skippedRows() as $row) {\n                unset($rows[$row - $startRow]);\n            }\n        }\n\n        return $rows;\n    }\n\n    /**\n     * @param  string  $lower\n     * @param  string  $upper\n     * @return \\Generator\n     */\n    protected function buildColumnRange(string $lower, string $upper)\n    {\n        $upper++;\n        for ($i = $lower; $i !== $upper; $i++) {\n            yield $i;\n        }\n    }\n\n    /**\n     * @return bool\n     */\n    private function hasRows(): bool\n    {\n        $startCell = 'A1';\n        if ($this->exportable instanceof WithCustomStartCell) {\n            $startCell = $this->exportable->startCell();\n        }\n\n        return $this->worksheet->cellExists($startCell);\n    }\n\n    /**\n     * @param  object  $sheetExport\n     * @return bool\n     */\n    private function hasStrictNullComparison($sheetExport): bool\n    {\n        if ($sheetExport instanceof WithStrictNullComparison) {\n            return true;\n        }\n\n        return config('excel.exports.strict_null_comparison', false);\n    }\n\n    /**\n     * @param  object|WithCustomChunkSize  $export\n     * @return int\n     */\n    private function getChunkSize($export): int\n    {\n        if ($export instanceof WithCustomChunkSize) {\n            return $export->chunkSize();\n        }\n\n        return $this->chunkSize;\n    }\n\n    /**\n     * @param  object|WithValidation  $import\n     * @return Closure|null\n     */\n    private function getPreparationCallback($import)\n    {\n        if (!$import instanceof WithValidation || !method_exists($import, 'prepareForValidation')) {\n            return null;\n        }\n\n        return function (array $data, int $index) use ($import) {\n            return $import->prepareForValidation($data, $index);\n        };\n    }\n}\n"
  },
  {
    "path": "src/Transactions/DbTransactionHandler.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Transactions;\n\nuse Illuminate\\Database\\ConnectionInterface;\n\nclass DbTransactionHandler implements TransactionHandler\n{\n    /**\n     * @var ConnectionInterface\n     */\n    private $connection;\n\n    /**\n     * @param  ConnectionInterface  $connection\n     */\n    public function __construct(ConnectionInterface $connection)\n    {\n        $this->connection = $connection;\n    }\n\n    /**\n     * @param  callable  $callback\n     * @return mixed\n     *\n     * @throws \\Throwable\n     */\n    public function __invoke(callable $callback)\n    {\n        return $this->connection->transaction($callback);\n    }\n}\n"
  },
  {
    "path": "src/Transactions/NullTransactionHandler.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Transactions;\n\nclass NullTransactionHandler implements TransactionHandler\n{\n    /**\n     * @param  callable  $callback\n     * @return mixed\n     */\n    public function __invoke(callable $callback)\n    {\n        return $callback();\n    }\n}\n"
  },
  {
    "path": "src/Transactions/TransactionHandler.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Transactions;\n\ninterface TransactionHandler\n{\n    /**\n     * @param  callable  $callback\n     * @return mixed\n     */\n    public function __invoke(callable $callback);\n}\n"
  },
  {
    "path": "src/Transactions/TransactionManager.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Transactions;\n\nuse Illuminate\\Support\\Facades\\DB;\nuse Illuminate\\Support\\Manager;\n\nclass TransactionManager extends Manager\n{\n    /**\n     * @return string\n     */\n    public function getDefaultDriver()\n    {\n        return config('excel.transactions.handler');\n    }\n\n    /**\n     * @return NullTransactionHandler\n     */\n    public function createNullDriver()\n    {\n        return new NullTransactionHandler();\n    }\n\n    /**\n     * @return DbTransactionHandler\n     */\n    public function createDbDriver()\n    {\n        return new DbTransactionHandler(\n            DB::connection(config('excel.transactions.db.connection'))\n        );\n    }\n}\n"
  },
  {
    "path": "src/Validators/Failure.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Validators;\n\nuse Illuminate\\Contracts\\Support\\Arrayable;\nuse JsonSerializable;\n\nclass Failure implements Arrayable, JsonSerializable\n{\n    /**\n     * @var int\n     */\n    protected $row;\n\n    /**\n     * @var string\n     */\n    protected $attribute;\n\n    /**\n     * @var array\n     */\n    protected $errors;\n\n    /**\n     * @var array\n     */\n    private $values;\n\n    /**\n     * @param  int  $row\n     * @param  string  $attribute\n     * @param  array  $errors\n     * @param  array  $values\n     */\n    public function __construct(int $row, string $attribute, array $errors, array $values = [])\n    {\n        $this->row       = $row;\n        $this->attribute = $attribute;\n        $this->errors    = $errors;\n        $this->values    = $values;\n    }\n\n    /**\n     * @return int\n     */\n    public function row(): int\n    {\n        return $this->row;\n    }\n\n    /**\n     * @return string\n     */\n    public function attribute(): string\n    {\n        return $this->attribute;\n    }\n\n    /**\n     * @return array\n     */\n    public function errors(): array\n    {\n        return $this->errors;\n    }\n\n    /**\n     * @return array\n     */\n    public function values(): array\n    {\n        return $this->values;\n    }\n\n    /**\n     * @return array\n     */\n    public function toArray()\n    {\n        return collect($this->errors)->map(function ($message) {\n            return __('There was an error on row :row. :message', ['row' => $this->row, 'message' => $message]);\n        })->all();\n    }\n\n    /**\n     * @return array\n     */\n    #[\\ReturnTypeWillChange]\n    public function jsonSerialize()\n    {\n        return [\n            'row'       => $this->row(),\n            'attribute' => $this->attribute(),\n            'errors'    => $this->errors(),\n            'values'    => $this->values(),\n        ];\n    }\n}\n"
  },
  {
    "path": "src/Validators/RowValidator.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Validators;\n\nuse Illuminate\\Contracts\\Validation\\Factory;\nuse Illuminate\\Support\\Str;\nuse Illuminate\\Validation\\ValidationException as IlluminateValidationException;\nuse Maatwebsite\\Excel\\Concerns\\SkipsOnFailure;\nuse Maatwebsite\\Excel\\Concerns\\WithValidation;\nuse Maatwebsite\\Excel\\Exceptions\\RowSkippedException;\n\nclass RowValidator\n{\n    /**\n     * @var Factory\n     */\n    private $validator;\n\n    /**\n     * @param  Factory  $validator\n     */\n    public function __construct(Factory $validator)\n    {\n        $this->validator = $validator;\n    }\n\n    /**\n     * @param  array  $rows\n     * @param  WithValidation  $import\n     *\n     * @throws ValidationException\n     * @throws RowSkippedException\n     */\n    public function validate(array $rows, WithValidation $import)\n    {\n        $rules      = $this->rules($import);\n        $messages   = $this->messages($import);\n        $attributes = $this->attributes($import);\n\n        try {\n            $validator = $this->validator->make($rows, $rules, $messages, $attributes);\n\n            if (method_exists($import, 'withValidator')) {\n                $import->withValidator($validator);\n            }\n\n            $validator->validate();\n        } catch (IlluminateValidationException $e) {\n            $failures = [];\n            foreach ($e->errors() as $attribute => $messages) {\n                $row           = strtok($attribute, '.');\n                $attributeName = strtok('');\n                $attributeName = $attributes['*.' . $attributeName] ?? $attributeName;\n\n                $failures[] = new Failure(\n                    $row,\n                    $attributeName,\n                    str_replace($attribute, $attributeName, $messages),\n                    $rows[$row] ?? []\n                );\n            }\n\n            if ($import instanceof SkipsOnFailure) {\n                $import->onFailure(...$failures);\n                throw new RowSkippedException(...$failures);\n            }\n\n            throw new ValidationException(\n                $e,\n                $failures\n            );\n        }\n    }\n\n    /**\n     * @param  WithValidation  $import\n     * @return array\n     */\n    private function messages(WithValidation $import): array\n    {\n        return method_exists($import, 'customValidationMessages')\n            ? $this->formatKey($import->customValidationMessages())\n            : [];\n    }\n\n    /**\n     * @param  WithValidation  $import\n     * @return array\n     */\n    private function attributes(WithValidation $import): array\n    {\n        return method_exists($import, 'customValidationAttributes')\n            ? $this->formatKey($import->customValidationAttributes())\n            : [];\n    }\n\n    /**\n     * @param  WithValidation  $import\n     * @return array\n     */\n    private function rules(WithValidation $import): array\n    {\n        return $this->formatKey($import->rules());\n    }\n\n    /**\n     * @param  array  $elements\n     * @return array\n     */\n    private function formatKey(array $elements): array\n    {\n        return collect($elements)->mapWithKeys(function ($rule, $attribute) {\n            $attribute = Str::startsWith($attribute, '*.') ? $attribute : '*.' . $attribute;\n\n            return [$attribute => $this->formatRule($rule)];\n        })->all();\n    }\n\n    /**\n     * @param  string|object|callable|array  $rules\n     * @return string|array\n     */\n    private function formatRule($rules)\n    {\n        if (is_array($rules)) {\n            foreach ($rules as $rule) {\n                $formatted[] = $this->formatRule($rule);\n            }\n\n            return $formatted ?? [];\n        }\n\n        if (is_object($rules) || is_callable($rules)) {\n            return $rules;\n        }\n\n        if (Str::contains($rules, 'required_without') && preg_match('/(.*?):(.*)/', $rules, $matches)) {\n            $column = array_map(function ($match) {\n                return Str::startsWith($match, '*.') ? $match : '*.' . $match;\n            }, explode(',', $matches[2]));\n\n            return $matches[1] . ':' . implode(',', $column);\n        }\n\n        if (Str::contains($rules, 'required_') && preg_match('/(.*?):(.*),(.*)/', $rules, $matches)) {\n            $column = Str::startsWith($matches[2], '*.') ? $matches[2] : '*.' . $matches[2];\n\n            return $matches[1] . ':' . $column . ',' . $matches[3];\n        }\n\n        return $rules;\n    }\n}\n"
  },
  {
    "path": "src/Validators/ValidationException.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Validators;\n\nuse Illuminate\\Validation\\ValidationException as IlluminateValidationException;\n\nclass ValidationException extends IlluminateValidationException\n{\n    /**\n     * @var Failure[]\n     */\n    protected $failures;\n\n    /**\n     * @param  IlluminateValidationException  $previous\n     * @param  array  $failures\n     */\n    public function __construct(IlluminateValidationException $previous, array $failures)\n    {\n        parent::__construct($previous->validator, $previous->response, $previous->errorBag);\n        $this->failures = $failures;\n    }\n\n    /**\n     * @return string[]\n     */\n    public function errors(): array\n    {\n        return collect($this->failures)->map->toArray()->all();\n    }\n\n    /**\n     * @return array\n     */\n    public function failures(): array\n    {\n        return $this->failures;\n    }\n}\n"
  },
  {
    "path": "src/Writer.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel;\n\nuse Maatwebsite\\Excel\\Concerns\\WithBackgroundColor;\nuse Maatwebsite\\Excel\\Concerns\\WithCustomValueBinder;\nuse Maatwebsite\\Excel\\Concerns\\WithDefaultStyles;\nuse Maatwebsite\\Excel\\Concerns\\WithEvents;\nuse Maatwebsite\\Excel\\Concerns\\WithMultipleSheets;\nuse Maatwebsite\\Excel\\Concerns\\WithProperties;\nuse Maatwebsite\\Excel\\Concerns\\WithTitle;\nuse Maatwebsite\\Excel\\Events\\BeforeExport;\nuse Maatwebsite\\Excel\\Events\\BeforeWriting;\nuse Maatwebsite\\Excel\\Factories\\WriterFactory;\nuse Maatwebsite\\Excel\\Files\\RemoteTemporaryFile;\nuse Maatwebsite\\Excel\\Files\\TemporaryFile;\nuse Maatwebsite\\Excel\\Files\\TemporaryFileFactory;\nuse PhpOffice\\PhpSpreadsheet\\Cell\\Cell;\nuse PhpOffice\\PhpSpreadsheet\\IOFactory;\nuse PhpOffice\\PhpSpreadsheet\\Spreadsheet;\nuse PhpOffice\\PhpSpreadsheet\\Style\\Color;\nuse PhpOffice\\PhpSpreadsheet\\Style\\Fill;\n\n/** @mixin Spreadsheet */\nclass Writer\n{\n    use DelegatedMacroable, HasEventBus;\n\n    /**\n     * @var Spreadsheet\n     */\n    protected $spreadsheet;\n\n    /**\n     * @var object\n     */\n    protected $exportable;\n\n    /**\n     * @var TemporaryFileFactory\n     */\n    protected $temporaryFileFactory;\n\n    /**\n     * @param  TemporaryFileFactory  $temporaryFileFactory\n     */\n    public function __construct(TemporaryFileFactory $temporaryFileFactory)\n    {\n        $this->temporaryFileFactory = $temporaryFileFactory;\n\n        $this->setDefaultValueBinder();\n    }\n\n    /**\n     * @param  object  $export\n     * @param  string  $writerType\n     * @return TemporaryFile\n     *\n     * @throws \\PhpOffice\\PhpSpreadsheet\\Exception\n     */\n    public function export($export, string $writerType): TemporaryFile\n    {\n        $this->open($export);\n\n        $sheetExports = [$export];\n        if ($export instanceof WithMultipleSheets) {\n            $sheetExports = $export->sheets();\n        }\n\n        foreach ($sheetExports as $sheetExport) {\n            $this->addNewSheet()->export($sheetExport);\n        }\n\n        return $this->write($export, $this->temporaryFileFactory->makeLocal(null, strtolower($writerType)), $writerType);\n    }\n\n    /**\n     * @param  object  $export\n     * @return $this\n     */\n    public function open($export)\n    {\n        $this->exportable = $export;\n\n        if ($export instanceof WithEvents) {\n            $this->registerListeners($export->registerEvents());\n        }\n\n        $this->exportable  = $export;\n        $this->spreadsheet = new Spreadsheet;\n        $this->spreadsheet->disconnectWorksheets();\n\n        if ($export instanceof WithCustomValueBinder) {\n            Cell::setValueBinder($export);\n        }\n\n        $this->handleDocumentProperties($export);\n\n        if ($export instanceof WithBackgroundColor) {\n            $defaultStyle    = $this->spreadsheet->getDefaultStyle();\n            $backgroundColor = $export->backgroundColor();\n\n            if (is_string($backgroundColor)) {\n                $defaultStyle->getFill()->setFillType(Fill::FILL_SOLID)->getStartColor()->setRGB($backgroundColor);\n            }\n\n            if (is_array($backgroundColor)) {\n                $defaultStyle->applyFromArray(['fill' => $backgroundColor]);\n            }\n\n            if ($backgroundColor instanceof Color) {\n                $defaultStyle->getFill()->setFillType(Fill::FILL_SOLID)->setStartColor($backgroundColor);\n            }\n        }\n\n        if ($export instanceof WithDefaultStyles) {\n            $defaultStyle = $this->spreadsheet->getDefaultStyle();\n            $styles       = $export->defaultStyles($defaultStyle);\n\n            if (is_array($styles)) {\n                $defaultStyle->applyFromArray($styles);\n            }\n        }\n\n        $this->raise(new BeforeExport($this, $this->exportable));\n\n        return $this;\n    }\n\n    /**\n     * @param  TemporaryFile  $tempFile\n     * @param  string  $writerType\n     * @return Writer\n     *\n     * @throws \\PhpOffice\\PhpSpreadsheet\\Reader\\Exception\n     */\n    public function reopen(TemporaryFile $tempFile, string $writerType)\n    {\n        $reader            = IOFactory::createReader($writerType);\n        $this->spreadsheet = $reader->load($tempFile->sync()->getLocalPath());\n\n        return $this;\n    }\n\n    /**\n     * Determine if the application is running in a serverless environment.\n     *\n     * @return bool\n     */\n    public function isRunningServerless(): bool\n    {\n        return isset($_ENV['AWS_LAMBDA_RUNTIME_API']);\n    }\n\n    /**\n     * @param  object  $export\n     * @param  TemporaryFile  $temporaryFile\n     * @param  string  $writerType\n     * @return TemporaryFile\n     *\n     * @throws \\PhpOffice\\PhpSpreadsheet\\Writer\\Exception\n     * @throws \\PhpOffice\\PhpSpreadsheet\\Exception\n     */\n    public function write($export, TemporaryFile $temporaryFile, string $writerType): TemporaryFile\n    {\n        $this->exportable = $export;\n\n        $this->spreadsheet->setActiveSheetIndex(0);\n\n        $this->raise(new BeforeWriting($this, $this->exportable));\n\n        $writer = WriterFactory::make(\n            $writerType,\n            $this->spreadsheet,\n            $export,\n            $temporaryFile->getLocalPath()\n        );\n\n        if ($temporaryFile instanceof RemoteTemporaryFile && !$temporaryFile->existsLocally() && !$this->isRunningServerless()) {\n            // just ensure that local copy exists (it creates the directory structure),\n            // no need to copy remote content since it will be overwritten below\n            $temporaryFile->sync(false);\n        }\n\n        $writer->save(\n            $temporaryFile->getLocalPath()\n        );\n\n        if ($temporaryFile instanceof RemoteTemporaryFile) {\n            $temporaryFile->updateRemote();\n            $temporaryFile->deleteLocalCopy();\n        }\n\n        $this->clearListeners();\n        $this->spreadsheet->disconnectWorksheets();\n        unset($this->spreadsheet);\n\n        return $temporaryFile;\n    }\n\n    /**\n     * @param  int|null  $sheetIndex\n     * @return Sheet\n     *\n     * @throws \\PhpOffice\\PhpSpreadsheet\\Exception\n     */\n    public function addNewSheet(?int $sheetIndex = null)\n    {\n        return new Sheet($this->spreadsheet->createSheet($sheetIndex));\n    }\n\n    /**\n     * @return Spreadsheet\n     */\n    public function getDelegate()\n    {\n        return $this->spreadsheet;\n    }\n\n    /**\n     * @return $this\n     */\n    public function setDefaultValueBinder()\n    {\n        Cell::setValueBinder(\n            app(config('excel.value_binder.default', DefaultValueBinder::class))\n        );\n\n        return $this;\n    }\n\n    /**\n     * @param  int  $sheetIndex\n     * @return Sheet\n     *\n     * @throws \\PhpOffice\\PhpSpreadsheet\\Exception\n     */\n    public function getSheetByIndex(int $sheetIndex)\n    {\n        return new Sheet($this->getDelegate()->getSheet($sheetIndex));\n    }\n\n    /**\n     * @param  string  $concern\n     * @return bool\n     */\n    public function hasConcern($concern): bool\n    {\n        return $this->exportable instanceof $concern;\n    }\n\n    /**\n     * @param  object  $export\n     */\n    protected function handleDocumentProperties($export)\n    {\n        $properties = config('excel.exports.properties', []);\n\n        if ($export instanceof WithProperties) {\n            $properties = array_merge($properties, $export->properties());\n        }\n\n        if ($export instanceof WithTitle) {\n            $properties = array_merge($properties, ['title' => $export->title()]);\n        }\n\n        $props = $this->spreadsheet->getProperties();\n\n        foreach (array_filter($properties) as $property => $value) {\n            switch ($property) {\n                case 'title':\n                    $props->setTitle($value);\n                    break;\n                case 'description':\n                    $props->setDescription($value);\n                    break;\n                case 'creator':\n                    $props->setCreator($value);\n                    break;\n                case 'lastModifiedBy':\n                    $props->setLastModifiedBy($value);\n                    break;\n                case 'subject':\n                    $props->setSubject($value);\n                    break;\n                case 'keywords':\n                    $props->setKeywords($value);\n                    break;\n                case 'category':\n                    $props->setCategory($value);\n                    break;\n                case 'manager':\n                    $props->setManager($value);\n                    break;\n                case 'company':\n                    $props->setCompany($value);\n                    break;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "tests/Cache/BatchCacheTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Cache;\n\nuse Composer\\InstalledVersions;\nuse Composer\\Semver\\VersionParser;\nuse DateInterval;\nuse Illuminate\\Cache\\ArrayStore;\nuse Illuminate\\Cache\\Events\\KeyWritten;\nuse Illuminate\\Cache\\Repository;\nuse Illuminate\\Support\\Facades\\Event;\nuse Maatwebsite\\Excel\\Cache\\BatchCache;\nuse Maatwebsite\\Excel\\Cache\\BatchCacheDeprecated;\nuse Maatwebsite\\Excel\\Cache\\CacheManager;\nuse Maatwebsite\\Excel\\Cache\\MemoryCache;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\nuse PHPUnit\\Framework\\Attributes\\DataProvider;\nuse Psr\\SimpleCache\\CacheInterface;\n\nclass BatchCacheTest extends TestCase\n{\n    /**\n     * @var Repository\n     */\n    private $cache;\n\n    /**\n     * @var MemoryCache\n     */\n    private $memory;\n\n    public function test_will_get_multiple_from_memory_if_cells_hold_in_memory()\n    {\n        $inMemory = [\n            'A1' => 'A1-value',\n            'A2' => 'A2-value',\n            'A3' => 'A3-value',\n        ];\n\n        $cache = $this->givenCache($inMemory);\n\n        $this->assertEquals(\n            $inMemory,\n            $cache->getMultiple(['A1', 'A2', 'A3'])\n        );\n\n        $this->assertEquals('A3-value', $cache->get('A3'));\n    }\n\n    public function test_will_get_multiple_from_cache_if_cells_are_persisted()\n    {\n        $inMemory  = [];\n        $persisted = [\n            'A1' => 'A1-value',\n            'A2' => 'A2-value',\n            'A3' => 'A3-value',\n        ];\n\n        $cache = $this->givenCache($inMemory, $persisted);\n\n        $this->assertEquals(\n            $persisted,\n            $cache->getMultiple(['A1', 'A2', 'A3'])\n        );\n\n        $this->assertEquals('A3-value', $cache->get('A3'));\n    }\n\n    public function test_will_get_multiple_from_cache_and_persisted()\n    {\n        $inMemory  = [\n            'A1' => 'A1-value',\n            'A2' => 'A2-value',\n            'A3' => 'A3-value',\n        ];\n        $persisted = [\n            'A4' => 'A4-value',\n            'A5' => 'A5-value',\n            'A6' => 'A6-value',\n        ];\n\n        $cache = $this->givenCache($inMemory, $persisted);\n\n        $this->assertEquals(\n            array_merge($inMemory, $persisted),\n            $cache->getMultiple(['A1', 'A2', 'A3', 'A4', 'A5', 'A6'])\n        );\n\n        $this->assertEquals('A3-value', $cache->get('A3'));\n        $this->assertEquals('A6-value', $cache->get('A6'));\n    }\n\n    public function test_it_persists_to_cache_when_memory_limit_reached_on_setting_a_value()\n    {\n        $memoryLimit = 3;\n        $persisted   = [];\n        $inMemory    = [\n            'A1' => 'A1-value',\n            'A2' => 'A2-value',\n            'A3' => 'A3-value',\n        ];\n\n        $cache = $this->givenCache($inMemory, $persisted, $memoryLimit);\n\n        // Setting a 4th value will reach the memory limit\n        $cache->set('A4', 'A4-value', 10000);\n\n        // Nothing in memory anymore\n        $this->assertEquals([], array_filter($this->memory->getMultiple(['A1', 'A2', 'A3', 'A4'])));\n\n        // All 4 cells show be persisted\n        $this->assertEquals([\n            'A1' => 'A1-value',\n            'A2' => 'A2-value',\n            'A3' => 'A3-value',\n            'A4' => 'A4-value',\n        ], $this->cache->getMultiple(['A1', 'A2', 'A3', 'A4']));\n\n        // Batch cache should return all 4 cells\n        $this->assertEquals([\n            'A1' => 'A1-value',\n            'A2' => 'A2-value',\n            'A3' => 'A3-value',\n            'A4' => 'A4-value',\n        ], $cache->getMultiple(['A1', 'A2', 'A3', 'A4']));\n    }\n\n    public function test_it_persists_to_cache_when_memory_limit_reached_on_setting_multiple_values()\n    {\n        $memoryLimit = 3;\n        $persisted   = [];\n        $inMemory    = [\n            'A1' => 'A1-value',\n            'A2' => 'A2-value',\n            'A3' => 'A3-value',\n        ];\n\n        $cache = $this->givenCache($inMemory, $persisted, $memoryLimit);\n\n        // Setting a 4th value will reach the memory limit\n        $cache->setMultiple([\n            'A4' => 'A4-value',\n            'A5' => 'A5-value',\n        ], 10000);\n\n        // Nothing in memory anymore\n        $this->assertEquals([], array_filter($this->memory->getMultiple(['A1', 'A2', 'A3', 'A4', 'A5'])));\n\n        // All 4 cells show be persisted\n        $this->assertEquals([\n            'A1' => 'A1-value',\n            'A2' => 'A2-value',\n            'A3' => 'A3-value',\n            'A4' => 'A4-value',\n            'A5' => 'A5-value',\n        ], $this->cache->getMultiple(['A1', 'A2', 'A3', 'A4', 'A5']));\n\n        // Batch cache should return all 4 cells\n        $this->assertEquals([\n            'A1' => 'A1-value',\n            'A2' => 'A2-value',\n            'A3' => 'A3-value',\n            'A4' => 'A4-value',\n            'A5' => 'A5-value',\n        ], $cache->getMultiple(['A1', 'A2', 'A3', 'A4', 'A5']));\n    }\n\n    /**\n     * @dataProvider defaultTTLDataProvider\n     */\n    #[DataProvider('defaultTTLDataProvider')]\n    public function test_it_writes_to_cache_with_default_ttl($defaultTTL, $receivedAs)\n    {\n        config()->set('excel.cache.default_ttl', $defaultTTL);\n\n        $cache = $this->givenCache(['A1' => 'A1-value'], [], 1);\n        $this->cache->setEventDispatcher(Event::fake());\n        $cache->set('A2', 'A2-value');\n\n        $expectedTTL = value($receivedAs);\n\n        $dispatchedCollection = Event::dispatched(\n            KeyWritten::class,\n            function (KeyWritten $event) use ($expectedTTL) {\n                return $event->seconds === $expectedTTL;\n            });\n\n        $this->assertCount(2, $dispatchedCollection);\n    }\n\n    public function test_it_writes_to_cache_with_a_dateinterval_ttl()\n    {\n        // DateInterval is 1 minute\n        config()->set('excel.cache.default_ttl', new DateInterval('PT1M'));\n\n        $cache = $this->givenCache(['A1' => 'A1-value'], [], 1);\n        $this->cache->setEventDispatcher(Event::fake());\n        $cache->set('A2', 'A2-value');\n\n        $dispatchedCollection = Event::dispatched(\n            KeyWritten::class,\n            function (KeyWritten $event) {\n                return $event->seconds >= 59 && $event->seconds <= 60;\n            });\n\n        $this->assertCount(2, $dispatchedCollection);\n    }\n\n    public function test_it_can_override_default_ttl()\n    {\n        config()->set('excel.cache.default_ttl', 1);\n\n        $cache = $this->givenCache(['A1' => 'A1-value'], [], 1);\n        $this->cache->setEventDispatcher(Event::fake());\n        $cache->set('A2', 'A2-value', null);\n\n        $dispatchedCollection = Event::dispatched(\n            KeyWritten::class,\n            function (KeyWritten $event) {\n                return $event->seconds === null;\n            });\n\n        $this->assertCount(2, $dispatchedCollection);\n    }\n\n    public static function defaultTTLDataProvider(): array\n    {\n        return [\n            'null (forever)' => [null, null],\n            'int value'      => [$value = rand(1, 100), $value],\n            'callable'       => [$closure = function () {\n                return 199;\n            }, $closure],\n        ];\n    }\n\n    /**\n     * Construct a BatchCache with a in memory store\n     * and an array cache, pretending to be a persistence store.\n     *\n     * @param  array  $memory\n     * @param  array  $persisted\n     * @param  int|null  $memoryLimit\n     * @return CacheInterface\n     */\n    private function givenCache(array $memory = [], array $persisted = [], $memoryLimit = null): CacheInterface\n    {\n        config()->set('excel.cache.batch.memory_limit', $memoryLimit ?: 60000);\n\n        $this->memory = $this->app->make(CacheManager::class)->createMemoryDriver();\n        $this->memory->setMultiple($memory);\n\n        $store = new ArrayStore();\n        $store->putMany($persisted, 10000);\n\n        $this->cache = new Repository($store);\n\n        if (!InstalledVersions::satisfies(new VersionParser, 'psr/simple-cache', '^3.0')) {\n            return new BatchCacheDeprecated(\n                $this->cache,\n                $this->memory,\n                config('excel.cache.default_ttl')\n            );\n        }\n\n        return new BatchCache(\n            $this->cache,\n            $this->memory,\n            config('excel.cache.default_ttl')\n        );\n    }\n}\n"
  },
  {
    "path": "tests/CellTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests;\n\nuse Maatwebsite\\Excel\\Cell;\nuse Maatwebsite\\Excel\\Middleware\\ConvertEmptyCellValuesToNull;\nuse Maatwebsite\\Excel\\Middleware\\TrimCellValue;\n\nclass CellTest extends TestCase\n{\n    public function test_can_get_cell_value()\n    {\n        config()->set('excel.imports.cells.middleware', []);\n\n        $worksheet = $this->read(__DIR__ . '/Data/Disks/Local/import-middleware.xlsx', 'Xlsx');\n\n        $this->assertEquals('test', Cell::make($worksheet->getActiveSheet(), 'A1')->getValue());\n\n        // By default spaces are not removed\n        $this->assertEquals('       ', Cell::make($worksheet->getActiveSheet(), 'A2')->getValue());\n    }\n\n    public function test_can_trim_empty_cells()\n    {\n        config()->set('excel.imports.cells.middleware', [\n            TrimCellValue::class,\n        ]);\n\n        $worksheet = $this->read(__DIR__ . '/Data/Disks/Local/import-middleware.xlsx', 'Xlsx');\n\n        $this->assertEquals('', Cell::make($worksheet->getActiveSheet(), 'A2')->getValue());\n\n        config()->set('excel.imports.cells.middleware', []);\n    }\n\n    public function test_convert_empty_cells_to_null()\n    {\n        config()->set('excel.imports.cells.middleware', [\n            TrimCellValue::class,\n            ConvertEmptyCellValuesToNull::class,\n        ]);\n\n        $worksheet = $this->read(__DIR__ . '/Data/Disks/Local/import-middleware.xlsx', 'Xlsx');\n\n        $this->assertEquals(null, Cell::make($worksheet->getActiveSheet(), 'A2')->getValue());\n\n        config()->set('excel.imports.cells.middleware', []);\n    }\n}\n"
  },
  {
    "path": "tests/Concerns/ExportableTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Concerns;\n\nuse Illuminate\\Contracts\\Support\\Responsable;\nuse Illuminate\\Http\\Request;\nuse Maatwebsite\\Excel\\Concerns\\Exportable;\nuse Maatwebsite\\Excel\\Excel;\nuse Maatwebsite\\Excel\\Exporter;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\EmptyExport;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\nuse Symfony\\Component\\HttpFoundation\\BinaryFileResponse;\n\nclass ExportableTest extends TestCase\n{\n    public function test_needs_to_have_a_file_name_when_downloading()\n    {\n        $this->expectException(\\Maatwebsite\\Excel\\Exceptions\\NoFilenameGivenException::class);\n        $this->expectExceptionMessage('A filename needs to be passed in order to download the export');\n\n        $export = new class\n        {\n            use Exportable;\n        };\n\n        $export->download();\n    }\n\n    public function test_needs_to_have_a_file_name_when_storing()\n    {\n        $this->expectException(\\Maatwebsite\\Excel\\Exceptions\\NoFilePathGivenException::class);\n        $this->expectExceptionMessage('A filepath needs to be passed in order to store the export');\n\n        $export = new class\n        {\n            use Exportable;\n        };\n\n        $export->store();\n    }\n\n    public function test_needs_to_have_a_file_name_when_queuing()\n    {\n        $this->expectException(\\Maatwebsite\\Excel\\Exceptions\\NoFilePathGivenException::class);\n        $this->expectExceptionMessage('A filepath needs to be passed in order to store the export');\n\n        $export = new class\n        {\n            use Exportable;\n        };\n\n        $export->queue();\n    }\n\n    public function test_responsable_needs_to_have_file_name_configured_inside_the_export()\n    {\n        $this->expectException(\\Maatwebsite\\Excel\\Exceptions\\NoFilenameGivenException::class);\n        $this->expectExceptionMessage('A filename needs to be passed in order to download the export');\n\n        $export = new class implements Responsable\n        {\n            use Exportable;\n        };\n\n        $export->toResponse(new Request());\n    }\n\n    public function test_is_responsable()\n    {\n        $export = new class implements Responsable\n        {\n            use Exportable;\n\n            protected $fileName = 'export.xlsx';\n        };\n\n        $this->assertInstanceOf(Responsable::class, $export);\n\n        $response = $export->toResponse(new Request());\n\n        $this->assertInstanceOf(BinaryFileResponse::class, $response);\n    }\n\n    public function test_can_have_customized_header()\n    {\n        $export   = new class\n        {\n            use Exportable;\n        };\n        $response = $export->download(\n            'name.csv',\n            Excel::CSV,\n            [\n                'Content-Type' => 'text/csv',\n            ]\n        );\n        $this->assertEquals('text/csv', $response->headers->get('Content-Type'));\n    }\n\n    public function test_can_set_custom_headers_in_export_class()\n    {\n        $export   = new class\n        {\n            use Exportable;\n\n            protected $fileName   = 'name.csv';\n            protected $writerType = Excel::CSV;\n            protected $headers    = [\n                'Content-Type' => 'text/csv',\n            ];\n        };\n        $response = $export->toResponse(request());\n\n        $this->assertEquals('text/csv', $response->headers->get('Content-Type'));\n    }\n\n    public function test_can_get_raw_export_contents()\n    {\n        $export = new EmptyExport;\n\n        $response = $export->raw(Excel::XLSX);\n\n        $this->assertNotEmpty($response);\n    }\n\n    public function test_can_have_customized_disk_options_when_storing()\n    {\n        $export = new EmptyExport;\n\n        $this->mock(Exporter::class)\n            ->shouldReceive('store')->once()\n            ->with($export, 'name.csv', 's3', Excel::CSV, ['visibility' => 'private']);\n\n        $export->store('name.csv', 's3', Excel::CSV, ['visibility' => 'private']);\n    }\n\n    public function test_can_have_customized_disk_options_when_queueing()\n    {\n        $export = new EmptyExport;\n\n        $this->mock(Exporter::class)\n            ->shouldReceive('queue')->once()\n            ->with($export, 'name.csv', 's3', Excel::CSV, ['visibility' => 'private']);\n\n        $export->queue('name.csv', 's3', Excel::CSV, ['visibility' => 'private']);\n    }\n\n    public function test_can_set_disk_options_in_export_class_when_storing()\n    {\n        $export = new class\n        {\n            use Exportable;\n\n            public $disk        = 's3';\n            public $writerType  = Excel::CSV;\n            public $diskOptions = ['visibility' => 'private'];\n        };\n\n        $this->mock(Exporter::class)\n            ->shouldReceive('store')->once()\n            ->with($export, 'name.csv', 's3', Excel::CSV, ['visibility' => 'private']);\n\n        $export->store('name.csv');\n    }\n\n    public function test_can_set_disk_options_in_export_class_when_queuing()\n    {\n        $export = new class\n        {\n            use Exportable;\n\n            public $disk        = 's3';\n            public $writerType  = Excel::CSV;\n            public $diskOptions = ['visibility' => 'private'];\n        };\n\n        $this->mock(Exporter::class)\n            ->shouldReceive('queue')->once()\n            ->with($export, 'name.csv', 's3', Excel::CSV, ['visibility' => 'private']);\n\n        $export->queue('name.csv');\n    }\n\n    public function test_can_override_export_class_disk_options_when_calling_store()\n    {\n        $export = new class\n        {\n            use Exportable;\n\n            public $diskOptions = ['visibility' => 'public'];\n        };\n\n        $this->mock(Exporter::class)\n            ->shouldReceive('store')->once()\n            ->with($export, 'name.csv', 's3', Excel::CSV, ['visibility' => 'private']);\n\n        $export->store('name.csv', 's3', Excel::CSV, ['visibility' => 'private']);\n    }\n\n    public function test_can_override_export_class_disk_options_when_calling_queue()\n    {\n        $export = new class\n        {\n            use Exportable;\n\n            public $diskOptions = ['visibility' => 'public'];\n        };\n\n        $this->mock(Exporter::class)\n            ->shouldReceive('queue')->once()\n            ->with($export, 'name.csv', 's3', Excel::CSV, ['visibility' => 'private']);\n\n        $export->queue('name.csv', 's3', Excel::CSV, ['visibility' => 'private']);\n    }\n\n    public function test_can_have_empty_disk_options_when_storing()\n    {\n        $export = new EmptyExport;\n\n        $this->mock(Exporter::class)\n            ->shouldReceive('store')->once()\n            ->with($export, 'name.csv', null, null, []);\n\n        $export->store('name.csv');\n    }\n\n    public function test_can_have_empty_disk_options_when_queueing()\n    {\n        $export = new EmptyExport;\n\n        $this->mock(Exporter::class)\n            ->shouldReceive('queue')->once()\n            ->with($export, 'name.csv', null, null, []);\n\n        $export->queue('name.csv');\n    }\n}\n"
  },
  {
    "path": "tests/Concerns/FromArrayTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Concerns;\n\nuse Maatwebsite\\Excel\\Concerns\\Exportable;\nuse Maatwebsite\\Excel\\Concerns\\FromArray;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\n\nclass FromArrayTest extends TestCase\n{\n    public function test_can_export_from_array()\n    {\n        $export = new class implements FromArray\n        {\n            use Exportable;\n\n            /**\n             * @return array\n             */\n            public function array(): array\n            {\n                return [\n                    ['test', 'test'],\n                    ['test', 'test'],\n                ];\n            }\n        };\n\n        $response = $export->store('from-array-store.xlsx');\n\n        $this->assertTrue($response);\n\n        $contents = $this->readAsArray(__DIR__ . '/../Data/Disks/Local/from-array-store.xlsx', 'Xlsx');\n\n        $this->assertEquals($export->array(), $contents);\n    }\n}\n"
  },
  {
    "path": "tests/Concerns/FromCollectionTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Concerns;\n\nuse Illuminate\\Foundation\\Bus\\PendingDispatch;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\EloquentLazyCollectionExport;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\EloquentLazyCollectionQueuedExport;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\QueuedExport;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\SheetWith100Rows;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\n\nclass FromCollectionTest extends TestCase\n{\n    public function test_can_export_from_collection()\n    {\n        $export = new SheetWith100Rows('A');\n\n        $response = $export->store('from-collection-store.xlsx');\n\n        $this->assertTrue($response);\n\n        $contents = $this->readAsArray(__DIR__ . '/../Data/Disks/Local/from-collection-store.xlsx', 'Xlsx');\n\n        $this->assertEquals($export->collection()->toArray(), $contents);\n    }\n\n    public function test_can_export_with_multiple_sheets_from_collection()\n    {\n        $export = new QueuedExport();\n\n        $response = $export->store('multiple-sheets-collection-store.xlsx');\n\n        $this->assertTrue($response);\n\n        foreach ($export->sheets() as $sheetIndex => $sheet) {\n            $spreadsheet = $this->read(\n                __DIR__ . '/../Data/Disks/Local/multiple-sheets-collection-store.xlsx',\n                'Xlsx'\n            );\n\n            $worksheet = $spreadsheet->getSheet($sheetIndex);\n\n            $this->assertEquals($sheet->collection()->toArray(), $worksheet->toArray());\n            $this->assertEquals($sheet->title(), $worksheet->getTitle());\n        }\n    }\n\n    public function test_can_export_from_lazy_collection()\n    {\n        if (!class_exists('\\Illuminate\\Support\\LazyCollection')) {\n            $this->markTestSkipped('Skipping test because LazyCollection is not supported');\n\n            return;\n        }\n\n        $export = new EloquentLazyCollectionExport();\n\n        $export->store('from-lazy-collection-store.xlsx');\n\n        $contents = $this->readAsArray(__DIR__ . '/../Data/Disks/Local/from-lazy-collection-store.xlsx', 'Xlsx');\n\n        $this->assertEquals(\n            $export->collection()->map(\n                function (array $item) {\n                    return array_values($item);\n                }\n            )->toArray(),\n            $contents\n        );\n    }\n\n    public function test_can_export_from_lazy_collection_with_queue()\n    {\n        if (!class_exists('\\Illuminate\\Support\\LazyCollection')) {\n            $this->markTestSkipped('Skipping test because LazyCollection is not supported');\n\n            return;\n        }\n\n        $export = new EloquentLazyCollectionQueuedExport();\n\n        $response = $export->queue('from-lazy-collection-store.xlsx');\n\n        $this->assertTrue($response instanceof PendingDispatch);\n\n        // Force dispatching via __destruct.\n        unset($response);\n\n        $contents = $this->readAsArray(__DIR__ . '/../Data/Disks/Local/from-lazy-collection-store.xlsx', 'Xlsx');\n\n        $this->assertEquals(\n            $export->collection()->map(\n                function (array $item) {\n                    return array_values($item);\n                }\n            )->toArray(),\n            $contents\n        );\n    }\n}\n"
  },
  {
    "path": "tests/Concerns/FromGeneratorTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Concerns;\n\nuse Generator;\nuse Maatwebsite\\Excel\\Concerns\\Exportable;\nuse Maatwebsite\\Excel\\Concerns\\FromGenerator;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\n\nclass FromGeneratorTest extends TestCase\n{\n    public function test_can_export_from_generator()\n    {\n        $export = new class implements FromGenerator\n        {\n            use Exportable;\n\n            /**\n             * @return Generator;\n             */\n            public function generator(): Generator\n            {\n                for ($i = 1; $i <= 2; $i++) {\n                    yield ['test', 'test'];\n                }\n            }\n        };\n\n        $response = $export->store('from-generator-store.xlsx');\n\n        $this->assertTrue($response);\n\n        $contents = $this->readAsArray(__DIR__ . '/../Data/Disks/Local/from-generator-store.xlsx', 'Xlsx');\n\n        $this->assertEquals(iterator_to_array($export->generator()), $contents);\n    }\n}\n"
  },
  {
    "path": "tests/Concerns/FromIteratorTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Concerns;\n\nuse ArrayIterator;\nuse Iterator;\nuse Maatwebsite\\Excel\\Concerns\\Exportable;\nuse Maatwebsite\\Excel\\Concerns\\FromIterator;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\n\nclass FromIteratorTest extends TestCase\n{\n    public function test_can_export_from_iterator()\n    {\n        $export = new class implements FromIterator\n        {\n            use Exportable;\n\n            /**\n             * @return array\n             */\n            public function array()\n            {\n                return [\n                    ['test', 'test'],\n                    ['test', 'test'],\n                ];\n            }\n\n            /**\n             * @return Iterator\n             */\n            public function iterator(): Iterator\n            {\n                return new ArrayIterator($this->array());\n            }\n        };\n\n        $response = $export->store('from-iterator-store.xlsx');\n\n        $this->assertTrue($response);\n\n        $contents = $this->readAsArray(__DIR__ . '/../Data/Disks/Local/from-iterator-store.xlsx', 'Xlsx');\n\n        $this->assertEquals($export->array(), $contents);\n    }\n}\n"
  },
  {
    "path": "tests/Concerns/FromQueryTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Concerns;\n\nuse Illuminate\\Support\\Facades\\DB;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database\\Group;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database\\User;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\FromGroupUsersQueuedQueryExport;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\FromNestedArraysQueryExport;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\FromNonEloquentQueryExport;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\FromUsersQueryExport;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\FromUsersQueryExportWithEagerLoad;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\FromUsersQueryExportWithPrepareRows;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\FromUsersQueryWithJoinExport;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\FromUsersScoutExport;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\n\nclass FromQueryTest extends TestCase\n{\n    /**\n     * Setup the test environment.\n     */\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $this->loadLaravelMigrations(['--database' => 'testing']);\n        $this->withFactories(__DIR__ . '/../Data/Stubs/Database/Factories');\n        $this->loadMigrationsFrom(dirname(__DIR__) . '/Data/Stubs/Database/Migrations');\n\n        $group = factory(Group::class)->create([\n            'name' => 'Group 1',\n        ]);\n\n        factory(User::class)->times(100)->create()->each(function (User $user) use ($group) {\n            $user->groups()->save($group);\n        });\n\n        $group_two = factory(Group::class)->create([\n            'name' => 'Group 2',\n        ]);\n\n        factory(User::class)->times(5)->create()->each(function (User $user) use ($group_two) {\n            $user->groups()->save($group_two);\n        });\n    }\n\n    public function test_can_export_from_query()\n    {\n        $export = new FromUsersQueryExport;\n\n        $response = $export->store('from-query-store.xlsx');\n\n        $this->assertTrue($response);\n\n        $contents = $this->readAsArray(__DIR__ . '/../Data/Disks/Local/from-query-store.xlsx', 'Xlsx');\n\n        $allUsers = $export->query()->get()->map(function (User $user) {\n            return array_values($user->toArray());\n        })->toArray();\n\n        $this->assertEquals($allUsers, $contents);\n    }\n\n    public function test_can_export_from_query_with_join()\n    {\n        $export = new FromUsersQueryWithJoinExport();\n\n        $response = $export->store('from-query-store.xlsx');\n\n        $this->assertTrue($response);\n\n        $contents = $this->readAsArray(__DIR__ . '/../Data/Disks/Local/from-query-store.xlsx', 'Xlsx');\n\n        $allUsers = $export->query->get()->map(function (User $user) {\n            return array_values($user->toArray());\n        })->toArray();\n\n        $this->assertEquals($allUsers, $contents);\n    }\n\n    public function test_can_export_from_relation_query_queued()\n    {\n        $export = new FromGroupUsersQueuedQueryExport();\n\n        $export->queue('from-query-store.xlsx');\n\n        $contents = $this->readAsArray(__DIR__ . '/../Data/Disks/Local/from-query-store.xlsx', 'Xlsx');\n\n        $allUsers = $export->query()->get()->map(function ($row) use ($export) {\n            return $export->map($row);\n        })->toArray();\n\n        $this->assertEquals($allUsers, $contents);\n    }\n\n    public function test_can_export_from_query_with_eager_loads()\n    {\n        DB::connection()->enableQueryLog();\n        $export = new FromUsersQueryExportWithEagerLoad();\n\n        $response = $export->store('from-query-with-eager-loads.xlsx');\n\n        $this->assertTrue($response);\n\n        // Should be 2 queries:\n        // 1) select all users\n        // 2) eager load query for groups\n        $this->assertCount(2, DB::getQueryLog());\n        DB::connection()->disableQueryLog();\n\n        $contents = $this->readAsArray(__DIR__ . '/../Data/Disks/Local/from-query-with-eager-loads.xlsx', 'Xlsx');\n\n        $allUsers = $export->query()->get()->map(function (User $user) use ($export) {\n            return $export->map($user);\n        })->toArray();\n\n        $this->assertEquals($allUsers, $contents);\n    }\n\n    public function test_can_export_from_query_with_eager_loads_and_queued()\n    {\n        DB::connection()->enableQueryLog();\n        $export = new FromUsersQueryExportWithEagerLoad();\n\n        $export->queue('from-query-with-eager-loads.xlsx');\n\n        // Should be 3 queries:\n        // 1) Count users to create chunked queues\n        // 2) select all users\n        // 3) eager load query for groups\n        $this->assertCount(3, DB::getQueryLog());\n        DB::connection()->disableQueryLog();\n\n        $contents = $this->readAsArray(__DIR__ . '/../Data/Disks/Local/from-query-with-eager-loads.xlsx', 'Xlsx');\n\n        $allUsers = $export->query()->get()->map(function (User $user) use ($export) {\n            return $export->map($user);\n        })->toArray();\n\n        $this->assertEquals($allUsers, $contents);\n    }\n\n    public function test_can_export_from_query_builder_without_using_eloquent()\n    {\n        $export = new FromNonEloquentQueryExport();\n\n        $response = $export->store('from-query-without-eloquent.xlsx');\n\n        $this->assertTrue($response);\n\n        $contents = $this->readAsArray(__DIR__ . '/../Data/Disks/Local/from-query-without-eloquent.xlsx', 'Xlsx');\n\n        $allUsers = $export->query()->get()->map(function ($row) {\n            return array_values((array) $row);\n        })->all();\n\n        $this->assertEquals($allUsers, $contents);\n    }\n\n    public function test_can_export_from_query_builder_without_using_eloquent_and_queued()\n    {\n        $export = new FromNonEloquentQueryExport();\n\n        $export->queue('from-query-without-eloquent.xlsx');\n\n        $contents = $this->readAsArray(__DIR__ . '/../Data/Disks/Local/from-query-without-eloquent.xlsx', 'Xlsx');\n\n        $allUsers = $export->query()->get()->map(function ($row) {\n            return array_values((array) $row);\n        })->all();\n\n        $this->assertEquals($allUsers, $contents);\n    }\n\n    public function test_can_export_from_query_builder_with_nested_arrays()\n    {\n        $export = new FromNestedArraysQueryExport();\n\n        $response = $export->store('from-query-with-nested-arrays.xlsx');\n\n        $this->assertTrue($response);\n\n        $contents = $this->readAsArray(__DIR__ . '/../Data/Disks/Local/from-query-with-nested-arrays.xlsx', 'Xlsx');\n\n        $this->assertEquals($this->format_nested_arrays_expected_data($export->query()->get()), $contents);\n    }\n\n    public function test_can_export_from_query_builder_with_nested_arrays_queued()\n    {\n        $export = new FromNestedArraysQueryExport();\n\n        $export->queue('from-query-with-nested-arrays.xlsx');\n\n        $contents = $this->readAsArray(__DIR__ . '/../Data/Disks/Local/from-query-with-nested-arrays.xlsx', 'Xlsx');\n\n        $this->assertEquals($this->format_nested_arrays_expected_data($export->query()->get()), $contents);\n    }\n\n    public function test_can_export_from_query_with_batch_caching()\n    {\n        config()->set('excel.cache.driver', 'batch');\n\n        $export = new FromUsersQueryExport;\n\n        $response = $export->store('from-query-store.xlsx');\n\n        $this->assertTrue($response);\n\n        $contents = $this->readAsArray(__DIR__ . '/../Data/Disks/Local/from-query-store.xlsx', 'Xlsx');\n\n        $allUsers = $export->query()->get()->map(function (User $user) {\n            return array_values($user->toArray());\n        })->toArray();\n\n        $this->assertEquals($allUsers, $contents);\n    }\n\n    public function test_can_export_from_query_with_prepare_rows()\n    {\n        $export = new FromUsersQueryExportWithPrepareRows;\n\n        $this->assertTrue(method_exists($export, 'prepareRows'));\n\n        $response = $export->store('from-query-store.xlsx');\n\n        $this->assertTrue($response);\n\n        $contents = $this->readAsArray(__DIR__ . '/../Data/Disks/Local/from-query-store.xlsx', 'Xlsx');\n\n        $allUsers = $export->query()->get()->map(function (User $user) {\n            $user->name .= '_prepared_name';\n\n            return array_values($user->toArray());\n        })->toArray();\n\n        $this->assertEquals($allUsers, $contents);\n    }\n\n    public function test_can_export_from_scout()\n    {\n        if (!class_exists('\\Laravel\\Scout\\Engines\\DatabaseEngine')) {\n            $this->markTestSkipped('Laravel Scout is too old');\n\n            return;\n        }\n\n        $export = new FromUsersScoutExport;\n\n        $response = $export->store('from-scout-store.xlsx');\n\n        $this->assertTrue($response);\n\n        $contents = $this->readAsArray(__DIR__ . '/../Data/Disks/Local/from-scout-store.xlsx', 'Xlsx');\n\n        $allUsers = $export->query()->get()->map(function (User $user) {\n            return array_values($user->toArray());\n        })->toArray();\n\n        $this->assertEquals($allUsers, $contents);\n    }\n\n    protected function format_nested_arrays_expected_data($groups)\n    {\n        $expected = [];\n        foreach ($groups as $group) {\n            $group_row = [$group->name, ''];\n\n            foreach ($group->users as $key => $user) {\n                if ($key === 0) {\n                    $group_row[1] = $user->email;\n                    $expected[]   = $group_row;\n                    continue;\n                }\n\n                $expected[] = ['', $user->email];\n            }\n        }\n\n        return $expected;\n    }\n}\n"
  },
  {
    "path": "tests/Concerns/FromViewTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Concerns;\n\nuse Illuminate\\Contracts\\View\\View;\nuse Illuminate\\Support\\Collection;\nuse Maatwebsite\\Excel\\Concerns\\Exportable;\nuse Maatwebsite\\Excel\\Concerns\\FromView;\nuse Maatwebsite\\Excel\\Concerns\\WithMultipleSheets;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database\\User;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\SheetForUsersFromView;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\n\nclass FromViewTest extends TestCase\n{\n    /**\n     * Setup the test environment.\n     */\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $this->withFactories(__DIR__ . '/../Data/Stubs/Database/Factories');\n    }\n\n    public function test_can_export_from_view()\n    {\n        /** @var Collection|User[] $users */\n        $users = factory(User::class)->times(100)->make();\n\n        $export = new class($users) implements FromView\n        {\n            use Exportable;\n\n            /**\n             * @var Collection\n             */\n            protected $users;\n\n            /**\n             * @param  Collection  $users\n             */\n            public function __construct(Collection $users)\n            {\n                $this->users = $users;\n            }\n\n            /**\n             * @return View\n             */\n            public function view(): View\n            {\n                return view('users', [\n                    'users' => $this->users,\n                ]);\n            }\n        };\n\n        $response = $export->store('from-view.xlsx');\n\n        $this->assertTrue($response);\n\n        $contents = $this->readAsArray(__DIR__ . '/../Data/Disks/Local/from-view.xlsx', 'Xlsx');\n\n        $expected = $users->map(function (User $user) {\n            return [\n                $user->name,\n                $user->email,\n            ];\n        })->prepend(['Name', 'Email'])->toArray();\n\n        $this->assertEquals($expected, $contents);\n    }\n\n    public function test_can_export_multiple_sheets_from_view()\n    {\n        /** @var Collection|User[] $users */\n        $users = factory(User::class)->times(300)->make();\n\n        $export = new class($users) implements WithMultipleSheets\n        {\n            use Exportable;\n\n            /**\n             * @var Collection\n             */\n            protected $users;\n\n            /**\n             * @param  Collection  $users\n             */\n            public function __construct(Collection $users)\n            {\n                $this->users = $users;\n            }\n\n            /**\n             * @return SheetForUsersFromView[]\n             */\n            public function sheets(): array\n            {\n                return [\n                    new SheetForUsersFromView($this->users->forPage(1, 100)),\n                    new SheetForUsersFromView($this->users->forPage(2, 100)),\n                    new SheetForUsersFromView($this->users->forPage(3, 100)),\n                ];\n            }\n        };\n\n        $response = $export->store('from-multiple-view.xlsx');\n\n        $this->assertTrue($response);\n\n        $contents = $this->readAsArray(__DIR__ . '/../Data/Disks/Local/from-multiple-view.xlsx', 'Xlsx', 0);\n\n        $expected = $users->forPage(1, 100)->map(function (User $user) {\n            return [\n                $user->name,\n                $user->email,\n            ];\n        })->prepend(['Name', 'Email'])->toArray();\n\n        $this->assertEquals(101, sizeof($contents));\n        $this->assertEquals($expected, $contents);\n\n        $contents = $this->readAsArray(__DIR__ . '/../Data/Disks/Local/from-multiple-view.xlsx', 'Xlsx', 2);\n\n        $expected = $users->forPage(3, 100)->map(function (User $user) {\n            return [\n                $user->name,\n                $user->email,\n            ];\n        })->prepend(['Name', 'Email'])->toArray();\n\n        $this->assertEquals(101, sizeof($contents));\n        $this->assertEquals($expected, $contents);\n    }\n}\n"
  },
  {
    "path": "tests/Concerns/ImportableTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Concerns;\n\nuse Illuminate\\Contracts\\Filesystem\\FileNotFoundException;\nuse Maatwebsite\\Excel\\Concerns\\Importable;\nuse Maatwebsite\\Excel\\Concerns\\ToArray;\nuse Maatwebsite\\Excel\\Excel;\nuse Maatwebsite\\Excel\\Importer;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\nuse PHPUnit\\Framework\\Assert;\n\nclass ImportableTest extends TestCase\n{\n    public function test_can_import_a_simple_xlsx_file()\n    {\n        $import = new class implements ToArray\n        {\n            use Importable;\n\n            /**\n             * @param  array  $array\n             */\n            public function array(array $array)\n            {\n                Assert::assertEquals([\n                    ['test', 'test'],\n                    ['test', 'test'],\n                ], $array);\n            }\n        };\n\n        $imported = $import->import('import.xlsx');\n\n        $this->assertInstanceOf(Importer::class, $imported);\n    }\n\n    public function test_can_import_a_simple_xlsx_file_from_uploaded_file()\n    {\n        $import = new class implements ToArray\n        {\n            use Importable;\n\n            /**\n             * @param  array  $array\n             */\n            public function array(array $array)\n            {\n                Assert::assertEquals([\n                    ['test', 'test'],\n                    ['test', 'test'],\n                ], $array);\n            }\n        };\n\n        $import->import($this->givenUploadedFile(__DIR__ . '/../Data/Disks/Local/import.xlsx'));\n    }\n\n    public function test_can_import_a_simple_csv_file_with_html_tags_inside()\n    {\n        $import = new class implements ToArray\n        {\n            use Importable;\n\n            /**\n             * @param  array  $array\n             */\n            public function array(array $array)\n            {\n                Assert::assertEquals([\n                    ['key1', 'A', 'row1'],\n                    ['key2', 'B', '<p>row2</p>'],\n                    ['key3', 'C', 'row3'],\n                    ['key4', 'D', 'row4'],\n                    ['key5', 'E', 'row5'],\n                    ['key6', 'F', '<a href=/url-example\">link</a>\"'],\n                ], $array);\n            }\n        };\n\n        $import->import('csv-with-html-tags.csv', 'local', Excel::CSV);\n    }\n\n    public function test_can_import_a_simple_xlsx_file_with_ignore_empty_set_to_true()\n    {\n        config()->set('excel.imports.ignore_empty', true);\n\n        $import = new class implements ToArray\n        {\n            use Importable;\n\n            /**\n             * @param  array  $array\n             */\n            public function array(array $array)\n            {\n                Assert::assertEquals([\n                    ['test', 'test'],\n                    ['test', 'test'],\n                ], $array);\n            }\n        };\n\n        $imported = $import->import('import-with-some-empty-rows.xlsx');\n\n        $this->assertInstanceOf(Importer::class, $imported);\n    }\n\n    public function test_can_import_a_simple_xlsx_file_with_ignore_empty_set_to_false()\n    {\n        config()->set('excel.imports.ignore_empty', false);\n\n        $import = new class implements ToArray\n        {\n            use Importable;\n\n            /**\n             * @param  array  $array\n             */\n            public function array(array $array)\n            {\n                Assert::assertEquals([\n                    ['test', 'test'],\n                    ['test', 'test'],\n                    ['', ''],\n                    ['', ''],\n                ], $array);\n            }\n        };\n\n        $imported = $import->import('import-with-some-empty-rows.xlsx');\n\n        $this->assertInstanceOf(Importer::class, $imported);\n    }\n\n    public function test_cannot_import_a_non_existing_xlsx_file()\n    {\n        $this->expectException(FileNotFoundException::class);\n\n        $import = new class\n        {\n            use Importable;\n        };\n\n        $import->import('doesnotexistanywhere.xlsx');\n    }\n}\n"
  },
  {
    "path": "tests/Concerns/OnEachRowTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Concerns;\n\nuse Maatwebsite\\Excel\\Concerns\\Importable;\nuse Maatwebsite\\Excel\\Concerns\\OnEachRow;\nuse Maatwebsite\\Excel\\Row;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\nuse PHPUnit\\Framework\\Assert;\n\nclass OnEachRowTest extends TestCase\n{\n    public function test_can_import_each_row_individually()\n    {\n        $import = new class implements OnEachRow\n        {\n            use Importable;\n\n            public $called = 0;\n\n            /**\n             * @param  Row  $row\n             */\n            public function onRow(Row $row)\n            {\n                foreach ($row->getCellIterator() as $cell) {\n                    Assert::assertEquals('test', $cell->getValue());\n                }\n\n                Assert::assertEquals([\n                    'test', 'test',\n                ], $row->toArray());\n\n                Assert::assertEquals('test', $row[0]);\n\n                $this->called++;\n            }\n        };\n\n        $import->import('import.xlsx');\n\n        $this->assertEquals(2, $import->called);\n    }\n\n    public function test_it_respects_the_end_column()\n    {\n        $import = new class implements OnEachRow\n        {\n            use Importable;\n\n            /**\n             * @param  Row  $row\n             */\n            public function onRow(Row $row)\n            {\n                // Accessing a row as an array calls toArray() without an end\n                // column. This saves the row in the cache, so we have to\n                // invalidate the cache once the end column changes\n                $row[0];\n\n                Assert::assertEquals([\n                    'test',\n                ], $row->toArray(null, false, true, 'A'));\n            }\n        };\n\n        $import->import('import.xlsx');\n    }\n}\n"
  },
  {
    "path": "tests/Concerns/RegistersEventListenersTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Concerns;\n\nuse Maatwebsite\\Excel\\Events\\AfterSheet;\nuse Maatwebsite\\Excel\\Events\\BeforeExport;\nuse Maatwebsite\\Excel\\Events\\BeforeImport;\nuse Maatwebsite\\Excel\\Events\\BeforeSheet;\nuse Maatwebsite\\Excel\\Events\\BeforeWriting;\nuse Maatwebsite\\Excel\\Reader;\nuse Maatwebsite\\Excel\\Sheet;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\BeforeExportListener;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\ExportWithEvents;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\ExportWithRegistersEventListeners;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\ImportWithRegistersEventListeners;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\nuse Maatwebsite\\Excel\\Writer;\nuse Symfony\\Component\\HttpFoundation\\BinaryFileResponse;\n\nclass RegistersEventListenersTest extends TestCase\n{\n    public function test_events_get_called_when_exporting()\n    {\n        $event = new ExportWithRegistersEventListeners();\n\n        $eventsTriggered = 0;\n\n        $event::$beforeExport = function ($event) use (&$eventsTriggered) {\n            $this->assertInstanceOf(BeforeExport::class, $event);\n            $this->assertInstanceOf(Writer::class, $event->writer);\n            $eventsTriggered++;\n        };\n\n        $event::$beforeWriting = function ($event) use (&$eventsTriggered) {\n            $this->assertInstanceOf(BeforeWriting::class, $event);\n            $this->assertInstanceOf(Writer::class, $event->writer);\n            $eventsTriggered++;\n        };\n\n        $event::$beforeSheet = function ($event) use (&$eventsTriggered) {\n            $this->assertInstanceOf(BeforeSheet::class, $event);\n            $this->assertInstanceOf(Sheet::class, $event->sheet);\n            $eventsTriggered++;\n        };\n\n        $event::$afterSheet = function ($event) use (&$eventsTriggered) {\n            $this->assertInstanceOf(AfterSheet::class, $event);\n            $this->assertInstanceOf(Sheet::class, $event->sheet);\n            $eventsTriggered++;\n        };\n\n        $this->assertInstanceOf(BinaryFileResponse::class, $event->download('filename.xlsx'));\n        $this->assertEquals(4, $eventsTriggered);\n    }\n\n    public function test_events_get_called_when_importing()\n    {\n        $event = new ImportWithRegistersEventListeners();\n\n        $eventsTriggered = 0;\n\n        $event::$beforeImport = function ($event) use (&$eventsTriggered) {\n            $this->assertInstanceOf(BeforeImport::class, $event);\n            $this->assertInstanceOf(Reader::class, $event->reader);\n            $eventsTriggered++;\n        };\n\n        $event::$beforeSheet = function ($event) use (&$eventsTriggered) {\n            $this->assertInstanceOf(BeforeSheet::class, $event);\n            $this->assertInstanceOf(Sheet::class, $event->sheet);\n            $eventsTriggered++;\n        };\n\n        $event::$afterSheet = function ($event) use (&$eventsTriggered) {\n            $this->assertInstanceOf(AfterSheet::class, $event);\n            $this->assertInstanceOf(Sheet::class, $event->sheet);\n            $eventsTriggered++;\n        };\n\n        $event->import('import.xlsx');\n        $this->assertEquals(3, $eventsTriggered);\n    }\n\n    public function test_can_have_invokable_class_as_listener()\n    {\n        $event = new ExportWithEvents();\n\n        $event->beforeExport = new BeforeExportListener(function ($event) {\n            $this->assertInstanceOf(BeforeExport::class, $event);\n            $this->assertInstanceOf(Writer::class, $event->writer);\n        });\n\n        $this->assertInstanceOf(BinaryFileResponse::class, $event->download('filename.xlsx'));\n    }\n}\n"
  },
  {
    "path": "tests/Concerns/RemembersChunkOffsetTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Concerns;\n\nuse Maatwebsite\\Excel\\Concerns\\Importable;\nuse Maatwebsite\\Excel\\Concerns\\RemembersChunkOffset;\nuse Maatwebsite\\Excel\\Concerns\\ToArray;\nuse Maatwebsite\\Excel\\Concerns\\WithChunkReading;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\n\nclass RemembersChunkOffsetTest extends TestCase\n{\n    public function test_can_set_and_get_chunk_offset()\n    {\n        $import = new class\n        {\n            use Importable;\n            use RemembersChunkOffset;\n        };\n\n        $import->setChunkOffset(50);\n\n        $this->assertEquals(50, $import->getChunkOffset());\n    }\n\n    public function test_can_access_chunk_offset_on_import_to_array_in_chunks()\n    {\n        $import = new class implements ToArray, WithChunkReading\n        {\n            use Importable;\n            use RemembersChunkOffset;\n\n            public $offsets = [];\n\n            public function array(array $array)\n            {\n                $this->offsets[] = $this->getChunkOffset();\n            }\n\n            public function chunkSize(): int\n            {\n                return 2000;\n            }\n        };\n\n        $import->import('import-batches.xlsx');\n\n        $this->assertEquals([1, 2001, 4001], $import->offsets);\n    }\n}\n"
  },
  {
    "path": "tests/Concerns/RemembersRowNumberTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Concerns;\n\nuse Maatwebsite\\Excel\\Concerns\\Importable;\nuse Maatwebsite\\Excel\\Concerns\\RemembersRowNumber;\nuse Maatwebsite\\Excel\\Concerns\\ToModel;\nuse Maatwebsite\\Excel\\Concerns\\WithBatchInserts;\nuse Maatwebsite\\Excel\\Concerns\\WithChunkReading;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\n\nclass RemembersRowNumberTest extends TestCase\n{\n    public function test_can_set_and_get_row_number()\n    {\n        $import = new class\n        {\n            use Importable;\n            use RemembersRowNumber;\n        };\n\n        $import->rememberRowNumber(50);\n\n        $this->assertEquals(50, $import->getRowNumber());\n    }\n\n    public function test_can_access_row_number_on_import_to_model()\n    {\n        $import = new class implements ToModel\n        {\n            use Importable;\n            use RemembersRowNumber;\n\n            public $rowNumbers = [];\n\n            public function model(array $row)\n            {\n                $this->rowNumbers[] = $this->getRowNumber();\n            }\n        };\n\n        $import->import('import-batches.xlsx');\n\n        $this->assertEquals([46, 47, 48, 49, 50, 51, 52, 53, 54, 55], array_slice($import->rowNumbers, 45, 10));\n    }\n\n    public function test_can_access_row_number_on_import_to_array_in_chunks()\n    {\n        $import = new class implements ToModel, WithChunkReading\n        {\n            use Importable;\n            use RemembersRowNumber;\n\n            public $rowNumbers = [];\n\n            public function chunkSize(): int\n            {\n                return 50;\n            }\n\n            public function model(array $row)\n            {\n                $this->rowNumbers[] = $this->getRowNumber();\n            }\n        };\n\n        $import->import('import-batches.xlsx');\n\n        $this->assertEquals([46, 47, 48, 49, 50, 51, 52, 53, 54, 55], array_slice($import->rowNumbers, 45, 10));\n    }\n\n    public function test_can_access_row_number_on_import_to_array_in_chunks_with_batch_inserts()\n    {\n        $import = new class implements ToModel, WithChunkReading, WithBatchInserts\n        {\n            use Importable;\n            use RemembersRowNumber;\n\n            public $rowNumbers = [];\n\n            public function chunkSize(): int\n            {\n                return 50;\n            }\n\n            public function model(array $row)\n            {\n                $this->rowNumbers[] = $this->rowNumber;\n            }\n\n            public function batchSize(): int\n            {\n                return 50;\n            }\n        };\n\n        $import->import('import-batches.xlsx');\n\n        $this->assertEquals([46, 47, 48, 49, 50, 51, 52, 53, 54, 55], array_slice($import->rowNumbers, 45, 10));\n    }\n}\n"
  },
  {
    "path": "tests/Concerns/ShouldQueueWithoutChainTest.php",
    "content": "<?php\n\nuse Illuminate\\Queue\\Events\\JobProcessed;\nuse Illuminate\\Queue\\SyncQueue;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Support\\Facades\\Queue;\nuse Maatwebsite\\Excel\\Jobs\\AfterImportJob;\nuse Maatwebsite\\Excel\\Jobs\\QueueImport;\nuse Maatwebsite\\Excel\\Jobs\\ReadChunk;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\QueueImportWithoutJobChaining;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\n\nclass ShouldQueueWithoutChainTest extends TestCase\n{\n    /**\n     * Setup the test environment.\n     */\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $this->loadLaravelMigrations(['--database' => 'testing']);\n        $this->loadMigrationsFrom(dirname(__DIR__) . '/Data/Stubs/Database/Migrations');\n    }\n\n    public function test_can_import_to_model_in_chunks()\n    {\n        DB::connection()->enableQueryLog();\n\n        $import = new QueueImportWithoutJobChaining();\n        $import->import('import-users.xlsx');\n\n        $this->assertCount(2, DB::getQueryLog());\n        DB::connection()->disableQueryLog();\n    }\n\n    public function test_can_import_to_model_without_job_chaining()\n    {\n        Queue::fake();\n\n        $import = new QueueImportWithoutJobChaining();\n        $import->import('import-users.xlsx');\n\n        Queue::assertPushed(ReadChunk::class, 2);\n        Queue::assertPushed(AfterImportJob::class, 1);\n        Queue::assertPushed(AfterImportJob::class, function ($import) {\n            return !is_null($import->delay);\n        });\n        Queue::assertNotPushed(QueueImport::class);\n    }\n\n    public function test_a_queue_name_can_be_specified_when_importing()\n    {\n        Queue::fake();\n\n        $import        = new QueueImportWithoutJobChaining();\n        $import->queue = 'queue-name';\n\n        $import->import('import-users.xlsx');\n\n        Queue::assertPushedOn('queue-name', ReadChunk::class);\n        Queue::assertPushedOn('queue-name', AfterImportJob::class);\n    }\n\n    public function test_the_cleanup_only_runs_when_all_jobs_are_done()\n    {\n        $fake = Queue::fake();\n\n        if (method_exists($fake, 'serializeAndRestore')) {\n            $fake->serializeAndRestore(); // More realism\n        }\n\n        $import = new QueueImportWithoutJobChaining();\n\n        $import->import('import-users.xlsx');\n\n        $jobs   = Queue::pushedJobs();\n        $chunks = collect($jobs[ReadChunk::class])->pluck('job');\n        $chunks->each(function (ReadChunk $chunk) {\n            self::assertFalse(ReadChunk::isComplete($chunk->getUniqueId()));\n        });\n        self::assertCount(2, $chunks);\n        $afterImport = $jobs[AfterImportJob::class][0]['job'];\n\n        if (!method_exists($fake, 'except')) {\n            /** @var SyncQueue $queue */\n            $fake = app(SyncQueue::class);\n            $fake->setContainer(app());\n        } else {\n            $fake->except([AfterImportJob::class, ReadChunk::class]);\n        }\n        $fake->push($chunks->first());\n        self::assertTrue(ReadChunk::isComplete($chunks->first()->getUniqueId()));\n        self::assertFalse(ReadChunk::isComplete($chunks->last()->getUniqueId()));\n\n        Event::listen(JobProcessed::class, function (JobProcessed $event) {\n            self::assertTrue($event->job->isReleased());\n        });\n        $fake->push($afterImport);\n        Event::forget(JobProcessed::class);\n        $fake->push($chunks->last());\n\n        Event::listen(JobProcessed::class, function (JobProcessed $event) {\n            self::assertFalse($event->job->isReleased());\n        });\n        $fake->push($afterImport);\n        Event::forget(JobProcessed::class);\n    }\n}\n"
  },
  {
    "path": "tests/Concerns/SkipsEmptyRowsTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Concerns;\n\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Support\\Collection;\nuse Maatwebsite\\Excel\\Concerns\\Importable;\nuse Maatwebsite\\Excel\\Concerns\\OnEachRow;\nuse Maatwebsite\\Excel\\Concerns\\SkipsEmptyRows;\nuse Maatwebsite\\Excel\\Concerns\\ToCollection;\nuse Maatwebsite\\Excel\\Concerns\\ToModel;\nuse Maatwebsite\\Excel\\Row;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\nuse PHPUnit\\Framework\\Assert;\n\nclass SkipsEmptyRowsTest extends TestCase\n{\n    public function test_skips_empty_rows_when_importing_to_collection()\n    {\n        $import = new class implements ToCollection, SkipsEmptyRows\n        {\n            use Importable;\n\n            public $called = false;\n\n            /**\n             * @param  Collection  $collection\n             */\n            public function collection(Collection $collection)\n            {\n                $this->called = true;\n\n                Assert::assertEquals([\n                    ['Test1', 'Test2'],\n                    ['Test3', 'Test4'],\n                    ['Test5', 'Test6'],\n                ], $collection->toArray());\n            }\n        };\n\n        $import->import('import-empty-rows.xlsx');\n\n        $this->assertTrue($import->called);\n    }\n\n    public function test_skips_empty_rows_when_importing_on_each_row()\n    {\n        $import = new class implements OnEachRow, SkipsEmptyRows\n        {\n            use Importable;\n\n            public $rows = 0;\n\n            /**\n             * @param  Row  $row\n             */\n            public function onRow(Row $row)\n            {\n                Assert::assertFalse($row->isEmpty());\n\n                $this->rows++;\n            }\n        };\n\n        $import->import('import-empty-rows.xlsx');\n\n        $this->assertEquals(3, $import->rows);\n    }\n\n    public function test_skips_empty_rows_when_importing_to_model()\n    {\n        $import = new class implements ToModel, SkipsEmptyRows\n        {\n            use Importable;\n\n            public $rows = 0;\n\n            /**\n             * @param  array  $row\n             * @return Model|Model[]|null\n             */\n            public function model(array $row)\n            {\n                $this->rows++;\n\n                return null;\n            }\n        };\n\n        $import->import('import-empty-rows.xlsx');\n\n        $this->assertEquals(3, $import->rows);\n    }\n\n    public function test_custom_skips_rows_when_importing_to_collection()\n    {\n        $import = new class implements SkipsEmptyRows, ToCollection\n        {\n            use Importable;\n\n            public $called = false;\n\n            /**\n             * @param  Collection  $collection\n             */\n            public function collection(Collection $collection)\n            {\n                $this->called = true;\n\n                Assert::assertEquals([\n                    ['Test1', 'Test2'],\n                    ['Test3', 'Test4'],\n                ], $collection->toArray());\n            }\n\n            public function isEmptyWhen(array $row)\n            {\n                return $row[0] == 'Test5' && $row[1] == 'Test6';\n            }\n        };\n\n        $import->import('import-empty-rows.xlsx');\n        $this->assertTrue($import->called);\n    }\n\n    public function test_custom_skips_rows_when_importing_to_model()\n    {\n        $import = new class implements SkipsEmptyRows, ToModel\n        {\n            use Importable;\n\n            public $called = false;\n\n            /**\n             * @param  array  $row\n             */\n            public function model(array $row)\n            {\n                Assert::assertEquals('Not empty', $row[0]);\n            }\n\n            public function isEmptyWhen(array $row): bool\n            {\n                $this->called = true;\n\n                return $row[0] === 'Empty';\n            }\n        };\n\n        $import->import('skip-empty-rows-with-is-empty-when.xlsx');\n        $this->assertTrue($import->called);\n    }\n\n    public function test_custom_skips_rows_when_using_oneachrow()\n    {\n        $import = new class implements SkipsEmptyRows, OnEachRow\n        {\n            use Importable;\n\n            public $called = false;\n\n            /**\n             * @param  array  $row\n             */\n            public function onRow(Row $row)\n            {\n                Assert::assertEquals('Not empty', $row[0]);\n            }\n\n            public function isEmptyWhen(array $row): bool\n            {\n                $this->called = true;\n\n                return $row[0] === 'Empty';\n            }\n        };\n\n        $import->import('skip-empty-rows-with-is-empty-when.xlsx');\n        $this->assertTrue($import->called);\n    }\n}\n"
  },
  {
    "path": "tests/Concerns/SkipsOnErrorTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Concerns;\n\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Database\\QueryException;\nuse Illuminate\\Validation\\Rule;\nuse Maatwebsite\\Excel\\Concerns\\Importable;\nuse Maatwebsite\\Excel\\Concerns\\OnEachRow;\nuse Maatwebsite\\Excel\\Concerns\\SkipsErrors;\nuse Maatwebsite\\Excel\\Concerns\\SkipsOnError;\nuse Maatwebsite\\Excel\\Concerns\\ToModel;\nuse Maatwebsite\\Excel\\Concerns\\WithValidation;\nuse Maatwebsite\\Excel\\Row;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database\\User;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\nuse Maatwebsite\\Excel\\Validators\\ValidationException;\nuse PHPUnit\\Framework\\Assert;\nuse Throwable;\n\nclass SkipsOnErrorTest extends TestCase\n{\n    /**\n     * Setup the test environment.\n     */\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $this->loadLaravelMigrations(['--database' => 'testing']);\n    }\n\n    public function test_can_skip_on_error()\n    {\n        $import = new class implements ToModel, SkipsOnError\n        {\n            use Importable;\n\n            public $errors = 0;\n\n            /**\n             * @param  array  $row\n             * @return Model|null\n             */\n            public function model(array $row)\n            {\n                return new User([\n                    'name'     => $row[0],\n                    'email'    => $row[1],\n                    'password' => 'secret',\n                ]);\n            }\n\n            /**\n             * @param  Throwable  $e\n             */\n            public function onError(Throwable $e)\n            {\n                Assert::assertInstanceOf(QueryException::class, $e);\n                Assert::stringContains($e->getMessage(), 'Duplicate entry \\'patrick@maatwebsite.nl\\'');\n\n                $this->errors++;\n            }\n        };\n\n        $import->import('import-users-with-duplicates.xlsx');\n\n        $this->assertEquals(1, $import->errors);\n\n        // Shouldn't have rollbacked other imported rows.\n        $this->assertDatabaseHas('users', [\n            'email' => 'patrick@maatwebsite.nl',\n        ]);\n\n        // Should have skipped inserting\n        $this->assertDatabaseMissing('users', [\n            'email' => 'taylor@laravel.com',\n        ]);\n    }\n\n    public function test_can_skip_errors_and_collect_all_errors_at_the_end()\n    {\n        $import = new class implements ToModel, SkipsOnError\n        {\n            use Importable, SkipsErrors;\n\n            /**\n             * @param  array  $row\n             * @return Model|null\n             */\n            public function model(array $row)\n            {\n                return new User([\n                    'name'     => $row[0],\n                    'email'    => $row[1],\n                    'password' => 'secret',\n                ]);\n            }\n        };\n\n        $import->import('import-users-with-duplicates.xlsx');\n\n        $this->assertCount(1, $import->errors());\n\n        /** @var Throwable $e */\n        $e = $import->errors()->first();\n\n        $this->assertInstanceOf(QueryException::class, $e);\n        $this->stringContains($e->getMessage(), 'Duplicate entry \\'patrick@maatwebsite.nl\\'');\n\n        // Shouldn't have rollbacked other imported rows.\n        $this->assertDatabaseHas('users', [\n            'email' => 'patrick@maatwebsite.nl',\n        ]);\n\n        // Should have skipped inserting\n        $this->assertDatabaseMissing('users', [\n            'email' => 'taylor@laravel.com',\n        ]);\n    }\n\n    public function test_can_skip_on_error_when_using_oneachrow_with_validation()\n    {\n        $import = new class implements OnEachRow, WithValidation, SkipsOnError\n        {\n            use Importable;\n\n            public $errors        = 0;\n            public $processedRows = 0;\n\n            /**\n             * @param  Row  $row\n             */\n            public function onRow(Row $row)\n            {\n                $this->processedRows++;\n\n                // This will be called for valid rows\n                $rowArray = $row->toArray();\n\n                User::create([\n                    'name'     => $rowArray[0],\n                    'email'    => $rowArray[1],\n                    'password' => 'secret',\n                ]);\n            }\n\n            /**\n             * @return array\n             */\n            public function rules(): array\n            {\n                return [\n                    '1' => Rule::in(['patrick@maatwebsite.nl']),\n                ];\n            }\n\n            /**\n             * @param  Throwable  $e\n             */\n            public function onError(Throwable $e)\n            {\n                Assert::assertInstanceOf(ValidationException::class, $e);\n                Assert::stringContains($e->getMessage(), 'The selected 1 is invalid');\n\n                $this->errors++;\n            }\n        };\n\n        $import->import('import-users.xlsx');\n\n        $this->assertEquals(1, $import->errors);\n        $this->assertEquals(1, $import->processedRows); // Only the valid row should be processed\n\n        // Should have inserted the valid row\n        $this->assertDatabaseHas('users', [\n            'email' => 'patrick@maatwebsite.nl',\n        ]);\n\n        // Should have skipped inserting the invalid row\n        $this->assertDatabaseMissing('users', [\n            'email' => 'taylor@laravel.com',\n        ]);\n    }\n\n    public function test_can_skip_errors_and_collect_all_errors_when_using_oneachrow_with_validation()\n    {\n        $import = new class implements OnEachRow, WithValidation, SkipsOnError\n        {\n            use Importable, SkipsErrors;\n\n            public $processedRows = 0;\n\n            /**\n             * @param  Row  $row\n             */\n            public function onRow(Row $row)\n            {\n                $this->processedRows++;\n\n                // This will be called for valid rows\n                $rowArray = $row->toArray();\n\n                User::create([\n                    'name'     => $rowArray[0],\n                    'email'    => $rowArray[1],\n                    'password' => 'secret',\n                ]);\n            }\n\n            /**\n             * @return array\n             */\n            public function rules(): array\n            {\n                return [\n                    '1' => Rule::in(['patrick@maatwebsite.nl']),\n                ];\n            }\n        };\n\n        $import->import('import-users.xlsx');\n\n        $this->assertCount(1, $import->errors());\n        $this->assertEquals(1, $import->processedRows); // Only the valid row should be processed\n\n        /** @var Throwable $e */\n        $e = $import->errors()->first();\n\n        $this->assertInstanceOf(ValidationException::class, $e);\n        $this->stringContains($e->getMessage(), 'The selected 1 is invalid');\n\n        // Should have inserted the valid row\n        $this->assertDatabaseHas('users', [\n            'email' => 'patrick@maatwebsite.nl',\n        ]);\n\n        // Should have skipped inserting the invalid row\n        $this->assertDatabaseMissing('users', [\n            'email' => 'taylor@laravel.com',\n        ]);\n    }\n\n    public function test_can_skip_on_error_when_exception_thrown_in_onrow()\n    {\n        $import = new class implements OnEachRow, SkipsOnError\n        {\n            use Importable;\n\n            public $errors        = 0;\n            public $processedRows = 0;\n\n            /**\n             * @param  Row  $row\n             */\n            public function onRow(Row $row)\n            {\n                $this->processedRows++;\n\n                $rowArray = $row->toArray();\n\n                // Throw an exception for the second row (Taylor Otwell)\n                if ($rowArray[1] === 'taylor@laravel.com') {\n                    throw new \\Exception('Custom error in onRow for Taylor');\n                }\n\n                User::create([\n                    'name'     => $rowArray[0],\n                    'email'    => $rowArray[1],\n                    'password' => 'secret',\n                ]);\n            }\n\n            /**\n             * @param  Throwable  $e\n             */\n            public function onError(Throwable $e)\n            {\n                Assert::assertInstanceOf(\\Exception::class, $e);\n                Assert::assertEquals('Custom error in onRow for Taylor', $e->getMessage());\n\n                $this->errors++;\n            }\n        };\n\n        $import->import('import-users.xlsx');\n\n        $this->assertEquals(1, $import->errors);\n        $this->assertEquals(2, $import->processedRows); // Both rows should be processed, but one throws exception\n\n        // Should have inserted the valid row\n        $this->assertDatabaseHas('users', [\n            'email' => 'patrick@maatwebsite.nl',\n        ]);\n\n        // Should have skipped inserting the row that threw exception\n        $this->assertDatabaseMissing('users', [\n            'email' => 'taylor@laravel.com',\n        ]);\n    }\n\n    public function test_can_skip_errors_and_collect_all_errors_when_exception_thrown_in_onrow()\n    {\n        $import = new class implements OnEachRow, SkipsOnError\n        {\n            use Importable, SkipsErrors;\n\n            public $processedRows = 0;\n\n            /**\n             * @param  Row  $row\n             */\n            public function onRow(Row $row)\n            {\n                $this->processedRows++;\n\n                $rowArray = $row->toArray();\n\n                // Throw an exception for the second row (Taylor Otwell)\n                if ($rowArray[1] === 'taylor@laravel.com') {\n                    throw new \\RuntimeException('Runtime error in onRow for Taylor');\n                }\n\n                User::create([\n                    'name'     => $rowArray[0],\n                    'email'    => $rowArray[1],\n                    'password' => 'secret',\n                ]);\n            }\n        };\n\n        $import->import('import-users.xlsx');\n\n        $this->assertCount(1, $import->errors());\n        $this->assertEquals(2, $import->processedRows); // Both rows should be processed, but one throws exception\n\n        /** @var Throwable $e */\n        $e = $import->errors()->first();\n\n        $this->assertInstanceOf(\\RuntimeException::class, $e);\n        $this->assertEquals('Runtime error in onRow for Taylor', $e->getMessage());\n\n        // Should have inserted the valid row\n        $this->assertDatabaseHas('users', [\n            'email' => 'patrick@maatwebsite.nl',\n        ]);\n\n        // Should have skipped inserting the row that threw exception\n        $this->assertDatabaseMissing('users', [\n            'email' => 'taylor@laravel.com',\n        ]);\n    }\n}\n"
  },
  {
    "path": "tests/Concerns/SkipsOnFailureTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Concerns;\n\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Support\\Collection;\nuse Illuminate\\Validation\\Rule;\nuse Maatwebsite\\Excel\\Concerns\\Importable;\nuse Maatwebsite\\Excel\\Concerns\\OnEachRow;\nuse Maatwebsite\\Excel\\Concerns\\SkipsFailures;\nuse Maatwebsite\\Excel\\Concerns\\SkipsOnFailure;\nuse Maatwebsite\\Excel\\Concerns\\ToCollection;\nuse Maatwebsite\\Excel\\Concerns\\ToModel;\nuse Maatwebsite\\Excel\\Concerns\\WithBatchInserts;\nuse Maatwebsite\\Excel\\Concerns\\WithValidation;\nuse Maatwebsite\\Excel\\Row;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database\\User;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\nuse Maatwebsite\\Excel\\Validators\\Failure;\nuse PHPUnit\\Framework\\Assert;\n\nclass SkipsOnFailureTest extends TestCase\n{\n    /**\n     * Setup the test environment.\n     */\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $this->loadLaravelMigrations(['--database' => 'testing']);\n    }\n\n    public function test_can_skip_on_error()\n    {\n        $import = new class implements ToModel, WithValidation, SkipsOnFailure\n        {\n            use Importable;\n\n            public $failures = 0;\n\n            /**\n             * @param  array  $row\n             * @return Model|null\n             */\n            public function model(array $row)\n            {\n                return new User([\n                    'name'     => $row[0],\n                    'email'    => $row[1],\n                    'password' => 'secret',\n                ]);\n            }\n\n            /**\n             * @return array\n             */\n            public function rules(): array\n            {\n                return [\n                    '1' => Rule::in(['patrick@maatwebsite.nl']),\n                ];\n            }\n\n            /**\n             * @param  Failure[]  $failures\n             */\n            public function onFailure(Failure ...$failures)\n            {\n                $failure = $failures[0];\n\n                Assert::assertEquals(2, $failure->row());\n                Assert::assertEquals('1', $failure->attribute());\n                Assert::assertEquals(['The selected 1 is invalid.'], $failure->errors());\n                Assert::assertEquals(['Taylor Otwell', 'taylor@laravel.com'], $failure->values());\n                Assert::assertEquals(2, $failure->jsonSerialize()['row']);\n                Assert::assertEquals('1', $failure->jsonSerialize()['attribute']);\n                Assert::assertEquals(['The selected 1 is invalid.'], $failure->jsonSerialize()['errors']);\n                Assert::assertEquals(['Taylor Otwell', 'taylor@laravel.com'], $failure->jsonSerialize()['values']);\n\n                $this->failures += \\count($failures);\n            }\n        };\n\n        $import->import('import-users.xlsx');\n\n        $this->assertEquals(1, $import->failures);\n\n        // Shouldn't have rollbacked other imported rows.\n        $this->assertDatabaseHas('users', [\n            'email' => 'patrick@maatwebsite.nl',\n        ]);\n\n        // Should have skipped inserting\n        $this->assertDatabaseMissing('users', [\n            'email' => 'taylor@laravel.com',\n        ]);\n    }\n\n    public function test_skips_only_failed_rows_in_batch()\n    {\n        $import = new class implements ToModel, WithValidation, WithBatchInserts, SkipsOnFailure\n        {\n            use Importable;\n\n            public $failures = 0;\n\n            /**\n             * @param  array  $row\n             * @return Model|null\n             */\n            public function model(array $row)\n            {\n                return new User([\n                    'name'     => $row[0],\n                    'email'    => $row[1],\n                    'password' => 'secret',\n                ]);\n            }\n\n            /**\n             * @return array\n             */\n            public function rules(): array\n            {\n                return [\n                    '1' => Rule::in(['patrick@maatwebsite.nl']),\n                ];\n            }\n\n            /**\n             * @param  Failure[]  $failures\n             */\n            public function onFailure(Failure ...$failures)\n            {\n                $failure = $failures[0];\n\n                Assert::assertEquals(2, $failure->row());\n                Assert::assertEquals('1', $failure->attribute());\n                Assert::assertEquals(['The selected 1 is invalid.'], $failure->errors());\n\n                $this->failures += \\count($failures);\n            }\n\n            /**\n             * @return int\n             */\n            public function batchSize(): int\n            {\n                return 100;\n            }\n        };\n\n        $import->import('import-users.xlsx');\n\n        $this->assertEquals(1, $import->failures);\n\n        // Shouldn't have rollbacked/skipped the rest of the batch.\n        $this->assertDatabaseHas('users', [\n            'email' => 'patrick@maatwebsite.nl',\n        ]);\n\n        // Should have skipped inserting\n        $this->assertDatabaseMissing('users', [\n            'email' => 'taylor@laravel.com',\n        ]);\n    }\n\n    public function test_can_skip_failures_and_collect_all_failures_at_the_end()\n    {\n        $import = new class implements ToModel, WithValidation, SkipsOnFailure\n        {\n            use Importable, SkipsFailures;\n\n            /**\n             * @param  array  $row\n             * @return Model|null\n             */\n            public function model(array $row)\n            {\n                return new User([\n                    'name'     => $row[0],\n                    'email'    => $row[1],\n                    'password' => 'secret',\n                ]);\n            }\n\n            /**\n             * @return array\n             */\n            public function rules(): array\n            {\n                return [\n                    '1' => Rule::in(['patrick@maatwebsite.nl']),\n                ];\n            }\n        };\n\n        $import->import('import-users.xlsx');\n\n        $this->assertCount(1, $import->failures());\n\n        /** @var Failure $failure */\n        $failure = $import->failures()->first();\n\n        $this->assertEquals(2, $failure->row());\n        $this->assertEquals('1', $failure->attribute());\n        $this->assertEquals(['The selected 1 is invalid.'], $failure->errors());\n\n        // Shouldn't have rollbacked other imported rows.\n        $this->assertDatabaseHas('users', [\n            'email' => 'patrick@maatwebsite.nl',\n        ]);\n\n        // Should have skipped inserting\n        $this->assertDatabaseMissing('users', [\n            'email' => 'taylor@laravel.com',\n        ]);\n    }\n\n    public function test_can_validate_using_oneachrow_and_skipsonfailure()\n    {\n        $import = new class implements OnEachRow, WithValidation, SkipsOnFailure\n        {\n            use Importable, SkipsFailures;\n\n            /**\n             * @param  Row  $row\n             * @return Model|null\n             */\n            public function onRow(Row $row)\n            {\n                $row = $row->toArray();\n\n                return User::create([\n                    'name'     => $row[0],\n                    'email'    => $row[1],\n                    'password' => 'secret',\n                ]);\n            }\n\n            /**\n             * @return array\n             */\n            public function rules(): array\n            {\n                return [\n                    '1' => Rule::in(['patrick@maatwebsite.nl']),\n                ];\n            }\n        };\n        $this->assertEmpty(User::all());\n\n        $import->import('import-users.xlsx');\n\n        $this->assertCount(1, $import->failures());\n\n        // Shouldn't have rollbacked other imported rows.\n        $this->assertDatabaseHas('users', [\n            'email' => 'patrick@maatwebsite.nl',\n        ]);\n\n        // Should have skipped inserting\n        $this->assertDatabaseMissing('users', [\n            'email' => 'taylor@laravel.com',\n        ]);\n    }\n\n    public function test_can_validate_using_tocollection_and_skipsonfailure()\n    {\n        $import = new class implements ToCollection, WithValidation, SkipsOnFailure\n        {\n            use Importable, SkipsFailures;\n\n            /**\n             * @param  Row  $row\n             * @return Model|null\n             */\n            public function collection(Collection $rows)\n            {\n                $rows = $rows->each(function ($row) {\n                    return User::create([\n                        'name'     => $row[0],\n                        'email'    => $row[1],\n                        'password' => 'secret',\n                    ]);\n                });\n            }\n\n            /**\n             * @return array\n             */\n            public function rules(): array\n            {\n                return [\n                    '1' => Rule::in(['patrick@maatwebsite.nl']),\n                ];\n            }\n        };\n        $this->assertEmpty(User::all());\n\n        $import->import('import-users.xlsx');\n\n        $this->assertCount(1, $import->failures());\n\n        // Shouldn't have rollbacked other imported rows.\n        $this->assertDatabaseHas('users', [\n            'email' => 'patrick@maatwebsite.nl',\n        ]);\n\n        // Should have skipped inserting\n        $this->assertDatabaseMissing('users', [\n            'email' => 'taylor@laravel.com',\n        ]);\n    }\n}\n"
  },
  {
    "path": "tests/Concerns/ToArrayTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Concerns;\n\nuse Maatwebsite\\Excel\\Concerns\\Importable;\nuse Maatwebsite\\Excel\\Concerns\\ToArray;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\nuse PHPUnit\\Framework\\Assert;\n\nclass ToArrayTest extends TestCase\n{\n    public function test_can_import_to_array()\n    {\n        $import = new class implements ToArray\n        {\n            use Importable;\n\n            public $called = false;\n\n            /**\n             * @param  array  $array\n             */\n            public function array(array $array)\n            {\n                $this->called = true;\n\n                Assert::assertEquals([\n                    ['test', 'test'],\n                    ['test', 'test'],\n                ], $array);\n            }\n        };\n\n        $import->import('import.xlsx');\n\n        $this->assertTrue($import->called);\n    }\n\n    public function test_can_import_multiple_sheets_to_array()\n    {\n        $import = new class implements ToArray\n        {\n            use Importable;\n\n            public $called = 0;\n\n            /**\n             * @param  array  $array\n             */\n            public function array(array $array)\n            {\n                $this->called++;\n\n                $sheetNumber = $this->called;\n\n                Assert::assertEquals([\n                    [$sheetNumber . '.A1', $sheetNumber . '.B1'],\n                    [$sheetNumber . '.A2', $sheetNumber . '.B2'],\n                ], $array);\n            }\n        };\n\n        $import->import('import-multiple-sheets.xlsx');\n\n        $this->assertEquals(2, $import->called);\n    }\n}\n"
  },
  {
    "path": "tests/Concerns/ToCollectionTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Concerns;\n\nuse Illuminate\\Support\\Collection;\nuse Maatwebsite\\Excel\\Concerns\\Importable;\nuse Maatwebsite\\Excel\\Concerns\\ToCollection;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\nuse PHPUnit\\Framework\\Assert;\n\nclass ToCollectionTest extends TestCase\n{\n    public function test_can_import_to_collection()\n    {\n        $import = new class implements ToCollection\n        {\n            use Importable;\n\n            public $called = false;\n\n            /**\n             * @param  Collection  $collection\n             */\n            public function collection(Collection $collection)\n            {\n                $this->called = true;\n\n                Assert::assertEquals([\n                    ['test', 'test'],\n                    ['test', 'test'],\n                ], $collection->toArray());\n            }\n        };\n\n        $import->import('import.xlsx');\n\n        $this->assertTrue($import->called);\n    }\n\n    public function test_can_import_multiple_sheets_to_collection()\n    {\n        $import = new class implements ToCollection\n        {\n            use Importable;\n\n            public $called = 0;\n\n            /**\n             * @param  Collection  $collection\n             */\n            public function collection(Collection $collection)\n            {\n                $this->called++;\n\n                $sheetNumber = $this->called;\n\n                Assert::assertEquals([\n                    [$sheetNumber . '.A1', $sheetNumber . '.B1'],\n                    [$sheetNumber . '.A2', $sheetNumber . '.B2'],\n                ], $collection->toArray());\n            }\n        };\n\n        $import->import('import-multiple-sheets.xlsx');\n\n        $this->assertEquals(2, $import->called);\n    }\n}\n"
  },
  {
    "path": "tests/Concerns/ToModelTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Concerns;\n\nuse Faker\\Factory;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Support\\Collection;\nuse Illuminate\\Support\\Facades\\DB;\nuse Maatwebsite\\Excel\\Concerns\\Importable;\nuse Maatwebsite\\Excel\\Concerns\\PersistRelations;\nuse Maatwebsite\\Excel\\Concerns\\ToModel;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database\\Group;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database\\User;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\n\nclass ToModelTest extends TestCase\n{\n    /**\n     * Setup the test environment.\n     */\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $this->loadLaravelMigrations(['--database' => 'testing']);\n        $this->loadMigrationsFrom(dirname(__DIR__) . '/Data/Stubs/Database/Migrations');\n    }\n\n    public function test_can_import_each_row_to_model()\n    {\n        DB::connection()->enableQueryLog();\n\n        $import = new class implements ToModel\n        {\n            use Importable;\n\n            /**\n             * @param  array  $row\n             * @return Model|Model[]|null\n             */\n            public function model(array $row)\n            {\n                return new User([\n                    'name'     => $row[0],\n                    'email'    => $row[1],\n                    'password' => 'secret',\n                ]);\n            }\n        };\n\n        $import->import('import-users.xlsx');\n\n        $this->assertCount(2, DB::getQueryLog());\n        DB::connection()->disableQueryLog();\n\n        $this->assertDatabaseHas('users', [\n            'name'  => 'Patrick Brouwers',\n            'email' => 'patrick@maatwebsite.nl',\n        ]);\n\n        $this->assertDatabaseHas('users', [\n            'name'  => 'Taylor Otwell',\n            'email' => 'taylor@laravel.com',\n        ]);\n    }\n\n    public function test_has_timestamps_when_imported_single_model()\n    {\n        $import = new class implements ToModel\n        {\n            use Importable;\n\n            /**\n             * @param  array  $row\n             * @return Model|Model[]|null\n             */\n            public function model(array $row)\n            {\n                return new User([\n                    'name'     => $row[0],\n                    'email'    => $row[1],\n                    'password' => 'secret',\n                ]);\n            }\n        };\n\n        $import->import('import-users.xlsx');\n\n        $user = User::first();\n\n        $this->assertNotNull($user->created_at);\n        $this->assertNotNull($user->updated_at);\n    }\n\n    public function test_can_import_multiple_models_in_single_to_model()\n    {\n        DB::connection()->enableQueryLog();\n\n        $import = new class implements ToModel\n        {\n            use Importable;\n\n            /**\n             * @param  array  $row\n             * @return Model|Model[]|null\n             */\n            public function model(array $row)\n            {\n                $user1 = new User([\n                    'name'     => $row[0],\n                    'email'    => $row[1],\n                    'password' => 'secret',\n                ]);\n\n                $faker = Factory::create();\n\n                $user2 = new User([\n                    'name'     => $faker->name,\n                    'email'    => $faker->email,\n                    'password' => 'secret',\n                ]);\n\n                return [$user1, $user2];\n            }\n        };\n\n        $import->import('import-users.xlsx');\n\n        $this->assertCount(4, DB::getQueryLog());\n        DB::connection()->disableQueryLog();\n    }\n\n    public function test_can_import_multiple_different_types_of_models_in_single_to_model()\n    {\n        DB::connection()->enableQueryLog();\n\n        $import = new class implements ToModel\n        {\n            use Importable;\n\n            /**\n             * @param  array  $row\n             * @return Model|Model[]|null\n             */\n            public function model(array $row)\n            {\n                $user = new User([\n                    'name'     => $row[0],\n                    'email'    => $row[1],\n                    'password' => 'secret',\n                ]);\n\n                $group = new Group([\n                    'name' => $row[0],\n                ]);\n\n                return [$user, $group];\n            }\n        };\n\n        $import->import('import-users.xlsx');\n\n        $this->assertCount(4, DB::getQueryLog());\n        $this->assertEquals(2, User::count());\n        $this->assertEquals(2, Group::count());\n        DB::connection()->disableQueryLog();\n    }\n\n    public function test_can_import_models_with_belongs_to_relations()\n    {\n        User::query()->truncate();\n        Group::query()->truncate();\n\n        DB::connection()->enableQueryLog();\n\n        $import = new class implements ToModel, PersistRelations\n        {\n            use Importable;\n\n            /**\n             * @param  array  $row\n             * @return Model|Model[]|null\n             */\n            public function model(array $row)\n            {\n                $user = new User([\n                    'name'     => $row[0],\n                    'email'    => $row[1],\n                    'password' => 'secret',\n                ]);\n\n                $user->group()->associate(\n                    new Group([\n                        'name' => $row[0],\n                    ])\n                );\n\n                return $user;\n            }\n        };\n\n        $import->import('import-users.xlsx');\n\n        $this->assertCount(6, DB::getQueryLog());\n\n        $users = User::all();\n        $users->each(function (User $user) {\n            $this->assertInstanceOf(Group::class, $user->group);\n            $this->assertIsInt($user->group->id);\n        });\n\n        $this->assertCount(2, $users);\n        $this->assertEquals(2, Group::count());\n        DB::connection()->disableQueryLog();\n    }\n\n    public function test_can_import_models_with_belongs_to_many_relations()\n    {\n        User::query()->truncate();\n        Group::query()->truncate();\n\n        DB::connection()->enableQueryLog();\n\n        $import = new class implements ToModel, PersistRelations\n        {\n            use Importable;\n\n            /**\n             * @param  array  $row\n             * @return Model|Model[]|null\n             */\n            public function model(array $row)\n            {\n                $user = new User([\n                    'name'     => $row[0],\n                    'email'    => $row[1],\n                    'password' => 'secret',\n                ]);\n\n                $user->setRelation('groups', new Collection([\n                    new Group([\n                        'name' => $row[0],\n                    ]),\n                ]));\n\n                return $user;\n            }\n        };\n\n        $import->import('import-users.xlsx');\n\n        $this->assertCount(6, DB::getQueryLog());\n\n        $users = User::all();\n        $users->each(function (User $user) {\n            $this->assertInstanceOf(Group::class, $user->groups->first());\n        });\n\n        $this->assertCount(2, $users);\n        $this->assertEquals(2, Group::count());\n        DB::connection()->disableQueryLog();\n    }\n}\n"
  },
  {
    "path": "tests/Concerns/WithBackgroundColorTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Concerns;\n\nuse Maatwebsite\\Excel\\Concerns\\Exportable;\nuse Maatwebsite\\Excel\\Concerns\\WithBackgroundColor;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\nuse PhpOffice\\PhpSpreadsheet\\Style\\Color;\nuse PhpOffice\\PhpSpreadsheet\\Style\\Fill;\n\nclass WithBackgroundColorTest extends TestCase\n{\n    public function test_can_configure_background_color_from_rgb_string()\n    {\n        $export = new class implements WithBackgroundColor\n        {\n            use Exportable;\n\n            public function backgroundColor()\n            {\n                return '000000';\n            }\n        };\n\n        $export->store('background-styles.xlsx');\n\n        $spreadsheet = $this->read(__DIR__ . '/../Data/Disks/Local/background-styles.xlsx', 'Xlsx');\n        $sheet       = $spreadsheet->getDefaultStyle();\n\n        $this->assertEquals(Fill::FILL_SOLID, $sheet->getFill()->getFillType());\n        $this->assertEquals('000000', $sheet->getFill()->getStartColor()->getRGB());\n    }\n\n    public function test_can_configure_background_color_as_array()\n    {\n        $export = new class implements WithBackgroundColor\n        {\n            use Exportable;\n\n            public function backgroundColor()\n            {\n                return [\n                    'fillType'   => Fill::FILL_GRADIENT_LINEAR,\n                    'startColor' => ['argb' => Color::COLOR_RED],\n                ];\n            }\n        };\n\n        $export->store('background-styles.xlsx');\n\n        $spreadsheet = $this->read(__DIR__ . '/../Data/Disks/Local/background-styles.xlsx', 'Xlsx');\n        $sheet       = $spreadsheet->getDefaultStyle();\n\n        $this->assertEquals(Fill::FILL_GRADIENT_LINEAR, $sheet->getFill()->getFillType());\n        $this->assertEquals(Color::COLOR_RED, $sheet->getFill()->getStartColor()->getARGB());\n    }\n\n    public function test_can_configure_background_color_with_color_instance()\n    {\n        $export = new class implements WithBackgroundColor\n        {\n            use Exportable;\n\n            public function backgroundColor()\n            {\n                return new Color(Color::COLOR_BLUE);\n            }\n        };\n\n        $export->store('background-styles.xlsx');\n\n        $spreadsheet = $this->read(__DIR__ . '/../Data/Disks/Local/background-styles.xlsx', 'Xlsx');\n        $sheet       = $spreadsheet->getDefaultStyle();\n\n        $this->assertEquals(Fill::FILL_SOLID, $sheet->getFill()->getFillType());\n        $this->assertEquals(Color::COLOR_BLUE, $sheet->getFill()->getStartColor()->getARGB());\n    }\n}\n"
  },
  {
    "path": "tests/Concerns/WithBatchInsertsTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Concerns;\n\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Support\\Facades\\DB;\nuse Maatwebsite\\Excel\\Concerns\\Importable;\nuse Maatwebsite\\Excel\\Concerns\\ToModel;\nuse Maatwebsite\\Excel\\Concerns\\WithBatchInserts;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database\\Group;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database\\User;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\n\nclass WithBatchInsertsTest extends TestCase\n{\n    /**\n     * Setup the test environment.\n     */\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $this->loadLaravelMigrations(['--database' => 'testing']);\n        $this->loadMigrationsFrom(dirname(__DIR__) . '/Data/Stubs/Database/Migrations');\n    }\n\n    public function test_can_import_to_model_in_batches()\n    {\n        DB::connection()->enableQueryLog();\n\n        $import = new class implements ToModel, WithBatchInserts\n        {\n            use Importable;\n\n            /**\n             * @param  array  $row\n             * @return Model|null\n             */\n            public function model(array $row)\n            {\n                return new User([\n                    'name'     => $row[0],\n                    'email'    => $row[1],\n                    'password' => 'secret',\n                ]);\n            }\n\n            /**\n             * @return int\n             */\n            public function batchSize(): int\n            {\n                return 2;\n            }\n        };\n\n        $import->import('import-users.xlsx');\n\n        $this->assertCount(1, DB::getQueryLog());\n        DB::connection()->disableQueryLog();\n\n        $this->assertDatabaseHas('users', [\n            'name'  => 'Patrick Brouwers',\n            'email' => 'patrick@maatwebsite.nl',\n        ]);\n\n        $this->assertDatabaseHas('users', [\n            'name'  => 'Taylor Otwell',\n            'email' => 'taylor@laravel.com',\n        ]);\n    }\n\n    public function test_can_import_to_model_in_batches_bigger_file()\n    {\n        DB::connection()->enableQueryLog();\n\n        $import = new class implements ToModel, WithBatchInserts\n        {\n            use Importable;\n\n            /**\n             * @param  array  $row\n             * @return Model|null\n             */\n            public function model(array $row)\n            {\n                return new Group([\n                    'name' => $row[0],\n                ]);\n            }\n\n            /**\n             * @return int\n             */\n            public function batchSize(): int\n            {\n                return 1000;\n            }\n        };\n\n        $import->import('import-batches.xlsx');\n\n        $this->assertCount(5000 / $import->batchSize(), DB::getQueryLog());\n        DB::connection()->disableQueryLog();\n    }\n\n    public function test_can_import_multiple_different_types_of_models_in_single_to_model()\n    {\n        DB::connection()->enableQueryLog();\n\n        $import = new class implements ToModel, WithBatchInserts\n        {\n            use Importable;\n\n            /**\n             * @param  array  $row\n             * @return Model|Model[]|null\n             */\n            public function model(array $row)\n            {\n                $user = new User([\n                    'name'     => $row[0],\n                    'email'    => $row[1],\n                    'password' => 'secret',\n                ]);\n\n                $group = new Group([\n                    'name' => $row[0],\n                ]);\n\n                return [$user, $group];\n            }\n\n            /**\n             * @return int\n             */\n            public function batchSize(): int\n            {\n                return 2;\n            }\n        };\n\n        $import->import('import-users.xlsx');\n\n        // Expected 2 batch queries, 1 for users, 1 for groups\n        $this->assertCount(2, DB::getQueryLog());\n\n        $this->assertEquals(2, User::count());\n        $this->assertEquals(2, Group::count());\n\n        DB::connection()->disableQueryLog();\n    }\n\n    public function test_has_timestamps_when_imported_in_batches()\n    {\n        $import = new class implements ToModel, WithBatchInserts\n        {\n            use Importable;\n\n            /**\n             * @param  array  $row\n             * @return Model|Model[]|null\n             */\n            public function model(array $row)\n            {\n                return new User([\n                    'name'     => $row[0],\n                    'email'    => $row[1],\n                    'password' => 'secret',\n                ]);\n            }\n\n            /**\n             * @return int\n             */\n            public function batchSize(): int\n            {\n                return 2;\n            }\n        };\n\n        $import->import('import-users.xlsx');\n\n        $user = User::first();\n\n        $this->assertNotNull($user->created_at);\n        $this->assertNotNull($user->updated_at);\n    }\n}\n"
  },
  {
    "path": "tests/Concerns/WithCalculatedFormulasTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Concerns;\n\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Maatwebsite\\Excel\\Concerns\\HasReferencesToOtherSheets;\nuse Maatwebsite\\Excel\\Concerns\\Importable;\nuse Maatwebsite\\Excel\\Concerns\\SkipsEmptyRows;\nuse Maatwebsite\\Excel\\Concerns\\ToArray;\nuse Maatwebsite\\Excel\\Concerns\\ToModel;\nuse Maatwebsite\\Excel\\Concerns\\WithCalculatedFormulas;\nuse Maatwebsite\\Excel\\Concerns\\WithMultipleSheets;\nuse Maatwebsite\\Excel\\Concerns\\WithStartRow;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\nuse PHPUnit\\Framework\\Assert;\n\nclass WithCalculatedFormulasTest extends TestCase\n{\n    public function test_by_default_does_not_calculate_formulas()\n    {\n        $import = new class implements ToArray\n        {\n            use Importable;\n\n            public $called = false;\n\n            /**\n             * @param  array  $array\n             */\n            public function array(array $array)\n            {\n                $this->called = true;\n\n                Assert::assertSame('=1+1', $array[0][0]);\n            }\n        };\n\n        $import->import('import-formulas.xlsx');\n\n        $this->assertTrue($import->called);\n    }\n\n    public function test_can_import_to_array_with_calculated_formulas()\n    {\n        $import = new class implements ToArray, WithCalculatedFormulas\n        {\n            use Importable;\n\n            public $called = false;\n\n            /**\n             * @param  array  $array\n             */\n            public function array(array $array)\n            {\n                $this->called = true;\n\n                Assert::assertSame(2, $array[0][0]);\n            }\n        };\n\n        $import->import('import-formulas.xlsx');\n\n        $this->assertTrue($import->called);\n    }\n\n    public function test_can_import_to_model_with_calculated_formulas()\n    {\n        $import = new class implements ToModel, WithCalculatedFormulas\n        {\n            use Importable;\n\n            public $called = false;\n\n            /**\n             * @param  array  $row\n             * @return Model|null\n             */\n            public function model(array $row)\n            {\n                $this->called = true;\n\n                Assert::assertSame(2, $row[0]);\n\n                return null;\n            }\n        };\n\n        $import->import('import-formulas.xlsx');\n\n        $this->assertTrue($import->called);\n    }\n\n    public function can_import_with_formulas_and_reference()\n    {\n        $import = new class implements ToModel, WithCalculatedFormulas, WithStartRow\n        {\n            use Importable;\n\n            public $called = false;\n\n            /**\n             * @param  array  $row\n             * @return Model|null\n             */\n            public function model(array $row)\n            {\n                $this->called = true;\n\n                Assert::assertSame('julien', $row[1]);\n\n                return null;\n            }\n\n            public function startRow(): int\n            {\n                return 2;\n            }\n        };\n\n        $import->import('import-external-reference.xls');\n\n        $this->assertTrue($import->called);\n    }\n\n    public function test_can_import_to_array_with_calculated_formulas_and_multi_sheet_references()\n    {\n        $import = new class implements WithMultipleSheets, HasReferencesToOtherSheets\n        {\n            use Importable;\n\n            public $test = 'test1';\n\n            public function sheets(): array\n            {\n                return [\n                    new class implements ToArray, HasReferencesToOtherSheets\n                    {\n                        public $test = 'test2';\n\n                        public function array(array $array)\n                        {\n                            Assert::assertEquals([\n                                ['1', '1'],\n                            ], $array);\n                        }\n                    },\n                    new class implements ToArray, WithCalculatedFormulas, HasReferencesToOtherSheets\n                    {\n                        public $test = 'test2';\n\n                        public function array(array $array)\n                        {\n                            Assert::assertEquals([\n                                ['2'],\n                            ], $array);\n                        }\n                    },\n                ];\n            }\n        };\n\n        $import->import('import-formulas-multiple-sheets.xlsx');\n    }\n\n    public function test_can_import_to_array_with_calculated_formulas_and_skips_empty()\n    {\n        $import = new class implements ToArray, WithCalculatedFormulas, SkipsEmptyRows\n        {\n            use Importable;\n\n            public $called = false;\n\n            /**\n             * @param  array  $array\n             */\n            public function array(array $array)\n            {\n                $this->called = true;\n\n                Assert::assertSame(2, $array[0][0]);\n            }\n        };\n\n        $import->import('import-formulas.xlsx');\n\n        $this->assertTrue($import->called);\n    }\n\n    public function test_can_import_to_model_with_calculated_formulas_and_skips_empty()\n    {\n        $import = new class implements ToModel, WithCalculatedFormulas, SkipsEmptyRows\n        {\n            use Importable;\n\n            public $called = false;\n\n            /**\n             * @param  array  $row\n             * @return Model|null\n             */\n            public function model(array $row)\n            {\n                $this->called = true;\n\n                Assert::assertSame(2, $row[0]);\n\n                return null;\n            }\n        };\n\n        $import->import('import-formulas.xlsx');\n\n        $this->assertTrue($import->called);\n    }\n}\n"
  },
  {
    "path": "tests/Concerns/WithChunkReadingTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Concerns;\n\nuse DateTime;\nuse Exception;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Support\\Facades\\DB;\nuse Maatwebsite\\Excel\\Concerns\\Importable;\nuse Maatwebsite\\Excel\\Concerns\\ToArray;\nuse Maatwebsite\\Excel\\Concerns\\ToModel;\nuse Maatwebsite\\Excel\\Concerns\\WithBatchInserts;\nuse Maatwebsite\\Excel\\Concerns\\WithChunkReading;\nuse Maatwebsite\\Excel\\Concerns\\WithEvents;\nuse Maatwebsite\\Excel\\Concerns\\WithFormatData;\nuse Maatwebsite\\Excel\\Concerns\\WithHeadingRow;\nuse Maatwebsite\\Excel\\Concerns\\WithMultipleSheets;\nuse Maatwebsite\\Excel\\Events\\AfterImport;\nuse Maatwebsite\\Excel\\Events\\BeforeImport;\nuse Maatwebsite\\Excel\\Events\\ImportFailed;\nuse Maatwebsite\\Excel\\Reader;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database\\Group;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database\\User;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\nuse PhpOffice\\PhpSpreadsheet\\Shared\\Date;\nuse PHPUnit\\Framework\\Assert;\nuse Throwable;\n\nclass WithChunkReadingTest extends TestCase\n{\n    /**\n     * Setup the test environment.\n     */\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $this->loadLaravelMigrations(['--database' => 'testing']);\n        $this->loadMigrationsFrom(dirname(__DIR__) . '/Data/Stubs/Database/Migrations');\n    }\n\n    public function test_can_import_to_model_in_chunks_un()\n    {\n        DB::connection()->enableQueryLog();\n\n        $import = new class implements ToModel, WithChunkReading, WithEvents\n        {\n            use Importable;\n\n            public $before = 0;\n            public $after  = 0;\n\n            /**\n             * @param  array  $row\n             * @return Model|null\n             */\n            public function model(array $row)\n            {\n                return new User([\n                    'name'     => $row[0],\n                    'email'    => $row[1],\n                    'password' => 'secret',\n                ]);\n            }\n\n            /**\n             * @return int\n             */\n            public function chunkSize(): int\n            {\n                return 1;\n            }\n\n            /**\n             * @return array\n             */\n            public function registerEvents(): array\n            {\n                return [\n                    BeforeImport::class => function (BeforeImport $event) {\n                        Assert::assertInstanceOf(Reader::class, $event->reader);\n                        $this->before++;\n                    },\n                    AfterImport::class  => function (AfterImport $event) {\n                        Assert::assertInstanceOf(Reader::class, $event->reader);\n                        $this->after++;\n                    },\n                ];\n            }\n        };\n\n        $import->import('import-users.xlsx');\n\n        $this->assertCount(2, DB::getQueryLog());\n        DB::connection()->disableQueryLog();\n\n        $this->assertEquals(1, $import->before, 'BeforeImport was not called or more than once.');\n        $this->assertEquals(1, $import->after, 'AfterImport was not called or more than once.');\n    }\n\n    public function test_can_import_to_model_in_chunks_and_insert_in_batches()\n    {\n        DB::connection()->enableQueryLog();\n\n        $import = new class implements ToModel, WithChunkReading, WithBatchInserts\n        {\n            use Importable;\n\n            /**\n             * @param  array  $row\n             * @return Model|null\n             */\n            public function model(array $row)\n            {\n                return new Group([\n                    'name' => $row[0],\n                ]);\n            }\n\n            /**\n             * @return int\n             */\n            public function chunkSize(): int\n            {\n                return 1000;\n            }\n\n            /**\n             * @return int\n             */\n            public function batchSize(): int\n            {\n                return 1000;\n            }\n        };\n\n        $import->import('import-batches.xlsx');\n\n        $this->assertCount(5000 / $import->batchSize(), DB::getQueryLog());\n        DB::connection()->disableQueryLog();\n    }\n\n    public function test_can_import_to_model_in_chunks_and_insert_in_batches_with_heading_row()\n    {\n        DB::connection()->enableQueryLog();\n\n        $import = new class implements ToModel, WithChunkReading, WithBatchInserts, WithHeadingRow\n        {\n            use Importable;\n\n            /**\n             * @param  array  $row\n             * @return Model|null\n             */\n            public function model(array $row)\n            {\n                return new Group([\n                    'name' => $row['name'],\n                ]);\n            }\n\n            /**\n             * @return int\n             */\n            public function chunkSize(): int\n            {\n                return 1000;\n            }\n\n            /**\n             * @return int\n             */\n            public function batchSize(): int\n            {\n                return 1000;\n            }\n        };\n\n        $import->import('import-batches-with-heading-row.xlsx');\n\n        $this->assertCount(5000 / $import->batchSize(), DB::getQueryLog());\n        DB::connection()->disableQueryLog();\n    }\n\n    public function test_can_import_csv_in_chunks_and_insert_in_batches()\n    {\n        DB::connection()->enableQueryLog();\n\n        $import = new class implements ToModel, WithChunkReading, WithBatchInserts\n        {\n            use Importable;\n\n            /**\n             * @param  array  $row\n             * @return Model|null\n             */\n            public function model(array $row)\n            {\n                return new Group([\n                    'name' => $row[0],\n                ]);\n            }\n\n            /**\n             * @return int\n             */\n            public function chunkSize(): int\n            {\n                return 1000;\n            }\n\n            /**\n             * @return int\n             */\n            public function batchSize(): int\n            {\n                return 1000;\n            }\n        };\n\n        $import->import('import-batches.csv');\n\n        $this->assertCount(10, DB::getQueryLog());\n        DB::connection()->disableQueryLog();\n    }\n\n    public function test_can_import_to_model_in_chunks_and_insert_in_batches_with_multiple_sheets()\n    {\n        DB::connection()->enableQueryLog();\n\n        $import = new class implements ToModel, WithChunkReading, WithBatchInserts\n        {\n            use Importable;\n\n            /**\n             * @param  array  $row\n             * @return Model|null\n             */\n            public function model(array $row)\n            {\n                return new Group([\n                    'name' => $row[0],\n                ]);\n            }\n\n            /**\n             * @return int\n             */\n            public function chunkSize(): int\n            {\n                return 1000;\n            }\n\n            /**\n             * @return int\n             */\n            public function batchSize(): int\n            {\n                return 1000;\n            }\n        };\n\n        $import->import('import-batches-multiple-sheets.xlsx');\n\n        $this->assertCount(10, DB::getQueryLog());\n        DB::connection()->disableQueryLog();\n    }\n\n    public function test_can_import_to_array_in_chunks()\n    {\n        $import = new class implements ToArray, WithChunkReading, WithFormatData\n        {\n            use Importable;\n\n            public $called = 0;\n\n            /**\n             * @param  array  $array\n             */\n            public function array(array $array)\n            {\n                $this->called++;\n\n                Assert::assertCount(100, $array);\n            }\n\n            /**\n             * @return int\n             */\n            public function chunkSize(): int\n            {\n                return 100;\n            }\n        };\n\n        $import->import('import-batches.xlsx');\n\n        $this->assertEquals(50, $import->called);\n    }\n\n    public function test_can_import_to_model_in_chunks_and_insert_in_batches_with_multiple_sheets_objects_by_index()\n    {\n        DB::connection()->enableQueryLog();\n\n        $import = new class implements WithMultipleSheets, WithChunkReading\n        {\n            use Importable;\n\n            /**\n             * @return int\n             */\n            public function chunkSize(): int\n            {\n                return 1000;\n            }\n\n            /**\n             * @return array\n             */\n            public function sheets(): array\n            {\n                return [\n                    new class implements ToModel, WithBatchInserts\n                    {\n                        /**\n                         * @param  array  $row\n                         * @return Model|null\n                         */\n                        public function model(array $row)\n                        {\n                            return new Group([\n                                'name' => $row[0],\n                            ]);\n                        }\n\n                        /**\n                         * @return int\n                         */\n                        public function batchSize(): int\n                        {\n                            return 1000;\n                        }\n                    },\n\n                    new class implements ToModel, WithBatchInserts\n                    {\n                        /**\n                         * @param  array  $row\n                         * @return Model|null\n                         */\n                        public function model(array $row)\n                        {\n                            return new Group([\n                                'name' => $row[0],\n                            ]);\n                        }\n\n                        /**\n                         * @return int\n                         */\n                        public function batchSize(): int\n                        {\n                            return 2000;\n                        }\n                    },\n                ];\n            }\n        };\n\n        $import->import('import-batches-multiple-sheets.xlsx');\n\n        $this->assertCount(10, DB::getQueryLog());\n        DB::connection()->disableQueryLog();\n    }\n\n    public function test_can_import_to_model_in_chunks_and_insert_in_batches_with_multiple_sheets_objects_by_name()\n    {\n        DB::connection()->enableQueryLog();\n\n        $import = new class implements WithMultipleSheets, WithChunkReading\n        {\n            use Importable;\n\n            /**\n             * @return int\n             */\n            public function chunkSize(): int\n            {\n                return 1000;\n            }\n\n            /**\n             * @return array\n             */\n            public function sheets(): array\n            {\n                return [\n                    'Worksheet' => new class implements ToModel, WithBatchInserts\n                    {\n                        /**\n                         * @param  array  $row\n                         * @return Model|null\n                         */\n                        public function model(array $row)\n                        {\n                            return new Group([\n                                'name' => $row[0],\n                            ]);\n                        }\n\n                        /**\n                         * @return int\n                         */\n                        public function batchSize(): int\n                        {\n                            return 1000;\n                        }\n                    },\n\n                    'Worksheet2' => new class implements ToModel, WithBatchInserts\n                    {\n                        /**\n                         * @param  array  $row\n                         * @return Model|null\n                         */\n                        public function model(array $row)\n                        {\n                            return new Group([\n                                'name' => $row[0],\n                            ]);\n                        }\n\n                        /**\n                         * @return int\n                         */\n                        public function batchSize(): int\n                        {\n                            return 2000;\n                        }\n                    },\n                ];\n            }\n        };\n\n        $import->import('import-batches-multiple-sheets.xlsx');\n\n        $this->assertCount(10, DB::getQueryLog());\n        DB::connection()->disableQueryLog();\n    }\n\n    public function test_can_catch_job_failed_in_chunks()\n    {\n        $import = new class implements ToModel, WithChunkReading, WithEvents\n        {\n            use Importable;\n\n            public $failed = false;\n\n            /**\n             * @param  array  $row\n             * @return Model|null\n             */\n            public function model(array $row)\n            {\n                throw new Exception('Something went wrong in the chunk');\n            }\n\n            /**\n             * @return int\n             */\n            public function chunkSize(): int\n            {\n                return 1;\n            }\n\n            /**\n             * @return array\n             */\n            public function registerEvents(): array\n            {\n                return [\n                    ImportFailed::class => function (ImportFailed $event) {\n                        Assert::assertInstanceOf(Throwable::class, $event->getException());\n                        Assert::assertEquals('Something went wrong in the chunk', $event->e->getMessage());\n\n                        $this->failed = true;\n                    },\n                ];\n            }\n        };\n\n        try {\n            $import->import('import-users.xlsx');\n        } catch (Throwable $e) {\n            $this->assertInstanceOf(Exception::class, $e);\n            $this->assertEquals('Something went wrong in the chunk', $e->getMessage());\n        }\n\n        $this->assertTrue($import->failed, 'ImportFailed event was not called.');\n    }\n\n    public function test_can_import_to_array_and_format_in_chunks()\n    {\n        config()->set('excel.imports.read_only', false);\n\n        $import = new class implements ToArray, WithChunkReading, WithFormatData\n        {\n            use Importable;\n\n            /**\n             * @param  array  $array\n             */\n            public function array(array $array)\n            {\n                Assert::assertCount(2, $array);\n                Assert::assertCount(1, $array[0]);\n                Assert::assertCount(1, $array[1]);\n                Assert::assertIsString($array[0][0]);\n                Assert::assertIsString($array[1][0]);\n                Assert::assertEquals('01/12/22', $array[0][0]);\n                Assert::assertEquals('2023-02-20', $array[1][0]);\n            }\n\n            /**\n             * @return int\n             */\n            public function chunkSize(): int\n            {\n                return 2;\n            }\n        };\n\n        $import->import('import-batches-with-date.xlsx');\n    }\n\n    public function test_can_import_to_array_in_chunks_without_formatting()\n    {\n        config()->set('excel.imports.read_only', true);\n\n        $import = new class implements ToArray, WithChunkReading\n        {\n            use Importable;\n\n            /**\n             * @param  array  $array\n             */\n            public function array(array $array)\n            {\n                Assert::assertCount(2, $array);\n                Assert::assertCount(1, $array[0]);\n                Assert::assertCount(1, $array[1]);\n                Assert::assertIsInt($array[0][0]);\n                Assert::assertIsInt($array[1][0]);\n                Assert::assertEquals((int) Date::dateTimeToExcel(DateTime::createFromFormat('Y-m-d', '2022-12-01')->setTime(0, 0, 0, 0)), $array[0][0]);\n                Assert::assertEquals((int) Date::dateTimeToExcel(DateTime::createFromFormat('Y-m-d', '2023-02-20')->setTime(0, 0, 0, 0)), $array[1][0]);\n            }\n\n            /**\n             * @return int\n             */\n            public function chunkSize(): int\n            {\n                return 2;\n            }\n        };\n\n        $import->import('import-batches-with-date.xlsx');\n    }\n}\n"
  },
  {
    "path": "tests/Concerns/WithColumnFormattingTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Concerns;\n\nuse Carbon\\Carbon;\nuse Composer\\InstalledVersions;\nuse Composer\\Semver\\VersionParser;\nuse Illuminate\\Support\\Collection;\nuse Maatwebsite\\Excel\\Concerns\\Exportable;\nuse Maatwebsite\\Excel\\Concerns\\FromCollection;\nuse Maatwebsite\\Excel\\Concerns\\WithColumnFormatting;\nuse Maatwebsite\\Excel\\Concerns\\WithMapping;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\nuse PhpOffice\\PhpSpreadsheet\\Shared\\Date;\nuse PhpOffice\\PhpSpreadsheet\\Style\\NumberFormat;\n\nclass WithColumnFormattingTest extends TestCase\n{\n    public function test_can_export_with_column_formatting()\n    {\n        $export = new class() implements FromCollection, WithMapping, WithColumnFormatting\n        {\n            use Exportable;\n\n            /**\n             * @return Collection\n             */\n            public function collection()\n            {\n                return collect([\n                    [Carbon::createFromDate(2018, 3, 6)],\n                    [Carbon::createFromDate(2018, 3, 7)],\n                    [Carbon::createFromDate(2018, 3, 8)],\n                    [Carbon::createFromDate(2021, 12, 6), 100],\n                ]);\n            }\n\n            /**\n             * @param  mixed  $row\n             * @return array\n             */\n            public function map($row): array\n            {\n                return [\n                    Date::dateTimeToExcel($row[0]),\n                    isset($row[1]) ? $row[1] : null,\n                ];\n            }\n\n            /**\n             * @return array\n             */\n            public function columnFormats(): array\n            {\n                return [\n                    'A'     => NumberFormat::FORMAT_DATE_DDMMYYYY,\n                    'B4:B4' => NumberFormat::FORMAT_CURRENCY_EUR,\n                ];\n            }\n        };\n\n        $response = $export->store('with-column-formatting-store.xlsx');\n\n        $this->assertTrue($response);\n\n        $actual = $this->readAsArray(__DIR__ . '/../Data/Disks/Local/with-column-formatting-store.xlsx', 'Xlsx');\n\n        $legacyPhpSpreadsheet = !InstalledVersions::satisfies(new VersionParser, 'phpoffice/phpspreadsheet', '^1.28');\n\n        $expected = [\n            ['06/03/2018', null],\n            ['07/03/2018', null],\n            ['08/03/2018', null],\n            ['06/12/2021', $legacyPhpSpreadsheet ? '100 €' : '100.00 €'],\n        ];\n\n        $this->assertEquals($expected, $actual);\n    }\n}\n"
  },
  {
    "path": "tests/Concerns/WithColumnLimitTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Concerns;\n\nuse Maatwebsite\\Excel\\Concerns\\Importable;\nuse Maatwebsite\\Excel\\Concerns\\SkipsEmptyRows;\nuse Maatwebsite\\Excel\\Concerns\\ToArray;\nuse Maatwebsite\\Excel\\Concerns\\WithColumnLimit;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\nuse PHPUnit\\Framework\\Assert;\n\nclass WithColumnLimitTest extends TestCase\n{\n    /**\n     * Setup the test environment.\n     */\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $this->loadLaravelMigrations(['--database' => 'testing']);\n    }\n\n    public function test_can_import_to_array_with_column_limit()\n    {\n        $import = new class implements ToArray, WithColumnLimit\n        {\n            use Importable;\n\n            /**\n             * @param  array  $array\n             */\n            public function array(array $array)\n            {\n                Assert::assertEquals([\n                    [\n                        'Patrick Brouwers',\n                    ],\n                    [\n                        'Taylor Otwell',\n                    ],\n                ], $array);\n            }\n\n            public function endColumn(): string\n            {\n                return 'A';\n            }\n        };\n\n        $import->import('import-users.xlsx');\n    }\n\n    public function test_can_import_to_array_with_column_limit_and_skips_empty_rows()\n    {\n        $import = new class implements ToArray, WithColumnLimit, SkipsEmptyRows\n        {\n            use Importable;\n\n            /**\n             * @param  array  $array\n             */\n            public function array(array $array)\n            {\n                Assert::assertEquals([\n                    [\n                        'Test1',\n                        'Test2',\n                        null,\n                        null,\n                    ],\n                    [\n                        'Test3',\n                        'Test4',\n                        null,\n                        null,\n                    ],\n                    [\n                        'Test5',\n                        'Test6',\n                        null,\n                        null,\n                    ],\n                ], $array);\n            }\n\n            public function endColumn(): string\n            {\n                return 'D';\n            }\n        };\n\n        $import->import('import-empty-rows.xlsx');\n    }\n}\n"
  },
  {
    "path": "tests/Concerns/WithColumnWidthsTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Concerns;\n\nuse Maatwebsite\\Excel\\Concerns\\Exportable;\nuse Maatwebsite\\Excel\\Concerns\\FromArray;\nuse Maatwebsite\\Excel\\Concerns\\WithColumnWidths;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\n\nclass WithColumnWidthsTest extends TestCase\n{\n    public function test_can_set_column_width()\n    {\n        $export = new class implements FromArray, WithColumnWidths\n        {\n            use Exportable;\n\n            public function columnWidths(): array\n            {\n                return [\n                    'A' => 55,\n                ];\n            }\n\n            public function array(): array\n            {\n                return [\n                    ['AA'],\n                    ['BB'],\n                ];\n            }\n        };\n\n        $export->store('with-column-widths.xlsx');\n\n        $spreadsheet = $this->read(__DIR__ . '/../Data/Disks/Local/with-column-widths.xlsx', 'Xlsx');\n\n        $this->assertEquals(55, $spreadsheet->getActiveSheet()->getColumnDimension('A')->getWidth());\n    }\n}\n"
  },
  {
    "path": "tests/Concerns/WithConditionalSheetsTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Concerns;\n\nuse Maatwebsite\\Excel\\Concerns\\Importable;\nuse Maatwebsite\\Excel\\Concerns\\ToArray;\nuse Maatwebsite\\Excel\\Concerns\\WithConditionalSheets;\nuse Maatwebsite\\Excel\\Concerns\\WithMultipleSheets;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\n\nclass WithConditionalSheetsTest extends TestCase\n{\n    /**\n     * Setup the test environment.\n     */\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $this->withFactories(__DIR__ . '/../Data/Stubs/Database/Factories');\n    }\n\n    public function test_can_select_which_sheets_will_be_imported()\n    {\n        $import = new class implements WithMultipleSheets\n        {\n            use Importable, WithConditionalSheets;\n\n            public $sheets = [];\n\n            public function __construct()\n            {\n                $this->init();\n            }\n\n            public function init()\n            {\n                $this->sheets = [\n                    'Sheet1' => new class implements ToArray\n                    {\n                        public $called = false;\n\n                        public function array(array $array)\n                        {\n                            $this->called = true;\n                        }\n                    },\n                    'Sheet2' => new class implements ToArray\n                    {\n                        public $called = false;\n\n                        public function array(array $array)\n                        {\n                            $this->called = true;\n                        }\n                    },\n                ];\n            }\n\n            /**\n             * @return array\n             */\n            public function conditionalSheets(): array\n            {\n                return $this->sheets;\n            }\n        };\n\n        $import->onlySheets('Sheet1')->import('import-multiple-sheets.xlsx');\n        $this->assertTrue($import->sheets['Sheet1']->called);\n        $this->assertFalse($import->sheets['Sheet2']->called);\n\n        $import->init();\n\n        $import->onlySheets('Sheet2')->import('import-multiple-sheets.xlsx');\n        $this->assertTrue($import->sheets['Sheet2']->called);\n        $this->assertFalse($import->sheets['Sheet1']->called);\n\n        $import->init();\n\n        $import->onlySheets(['Sheet1', 'Sheet2'])->import('import-multiple-sheets.xlsx');\n        $this->assertTrue($import->sheets['Sheet1']->called);\n        $this->assertTrue($import->sheets['Sheet2']->called);\n\n        $import->init();\n\n        $import->onlySheets('Sheet1', 'Sheet2')->import('import-multiple-sheets.xlsx');\n        $this->assertTrue($import->sheets['Sheet1']->called);\n        $this->assertTrue($import->sheets['Sheet2']->called);\n    }\n}\n"
  },
  {
    "path": "tests/Concerns/WithCustomCsvSettingsTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Concerns;\n\nuse Illuminate\\Support\\Collection;\nuse Maatwebsite\\Excel\\Concerns\\FromCollection;\nuse Maatwebsite\\Excel\\Concerns\\ToArray;\nuse Maatwebsite\\Excel\\Concerns\\WithCustomCsvSettings;\nuse Maatwebsite\\Excel\\Excel;\nuse Maatwebsite\\Excel\\HeadingRowImport;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\nuse PHPUnit\\Framework\\Assert;\n\nclass WithCustomCsvSettingsTest extends TestCase\n{\n    /**\n     * @var Excel\n     */\n    protected $SUT;\n\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $this->SUT = $this->app->make(Excel::class);\n    }\n\n    public function test_can_store_csv_export_with_custom_settings()\n    {\n        $export = new class implements FromCollection, WithCustomCsvSettings\n        {\n            /**\n             * @return Collection\n             */\n            public function collection()\n            {\n                return collect([\n                    ['A1', 'B1'],\n                    ['A2', 'B2'],\n                ]);\n            }\n\n            /**\n             * @return array\n             */\n            public function getCsvSettings(): array\n            {\n                return [\n                    'delimiter'              => ';',\n                    'enclosure'              => '',\n                    'line_ending'            => PHP_EOL,\n                    'use_bom'                => true,\n                    'include_separator_line' => true,\n                    'excel_compatibility'    => false,\n                    'output_encoding'        => '',\n                    'test_auto_detect'       => false,\n                ];\n            }\n        };\n\n        $this->SUT->store($export, 'custom-csv.csv');\n\n        $contents = file_get_contents(__DIR__ . '/../Data/Disks/Local/custom-csv.csv');\n\n        $this->assertStringContains('sep=;', $contents);\n        $this->assertStringContains('A1;B1', $contents);\n        $this->assertStringContains('A2;B2', $contents);\n    }\n\n    public function test_can_store_csv_export_with_custom_encoding()\n    {\n        $export = new class implements FromCollection, WithCustomCsvSettings\n        {\n            /**\n             * @return Collection\n             */\n            public function collection()\n            {\n                return collect([\n                    ['A1', '€ŠšŽžŒœŸ'],\n                    ['A2', 'åßàèòìù'],\n                ]);\n            }\n\n            /**\n             * @return array\n             */\n            public function getCsvSettings(): array\n            {\n                return [\n                    'delimiter'              => ';',\n                    'enclosure'              => '',\n                    'line_ending'            => PHP_EOL,\n                    'use_bom'                => false,\n                    'include_separator_line' => true,\n                    'excel_compatibility'    => false,\n                    'output_encoding'        => 'ISO-8859-15',\n                ];\n            }\n        };\n\n        $this->SUT->store($export, 'custom-csv-iso.csv');\n\n        $contents = file_get_contents(__DIR__ . '/../Data/Disks/Local/custom-csv-iso.csv');\n\n        Assert::assertEquals('ISO-8859-15', mb_detect_encoding($contents, 'ISO-8859-15', true));\n        Assert::assertFalse(mb_detect_encoding($contents, 'UTF-8', true));\n\n        $contents = mb_convert_encoding($contents, 'UTF-8', 'ISO-8859-15');\n\n        $this->assertStringContains('sep=;', $contents);\n        $this->assertStringContains('A1;€ŠšŽžŒœŸ', $contents);\n        $this->assertStringContains('A2;åßàèòìù', $contents);\n    }\n\n    public function test_can_read_csv_with_auto_detecting_delimiter_semicolon()\n    {\n        $this->assertEquals([\n            [\n                ['a1', 'b1'],\n            ],\n        ], (new HeadingRowImport())->toArray('csv-with-other-delimiter.csv'));\n    }\n\n    public function test_can_read_csv_with_auto_detecting_delimiter_comma()\n    {\n        $this->assertEquals([\n            [\n                ['a1', 'b1'],\n            ],\n        ], (new HeadingRowImport())->toArray('csv-with-comma.csv'));\n    }\n\n    public function test_can_read_csv_import_with_custom_settings()\n    {\n        $import = new class implements WithCustomCsvSettings, ToArray\n        {\n            /**\n             * @return array\n             */\n            public function getCsvSettings(): array\n            {\n                return [\n                    'delimiter'        => ';',\n                    'enclosure'        => '',\n                    'escape_character' => '\\\\',\n                    'contiguous'       => true,\n                    'input_encoding'   => 'UTF-8',\n                ];\n            }\n\n            /**\n             * @param  array  $array\n             */\n            public function array(array $array)\n            {\n                Assert::assertEquals([\n                    ['A1', 'B1'],\n                    ['A2', 'B2'],\n                ], $array);\n            }\n        };\n\n        $this->SUT->import($import, 'csv-with-other-delimiter.csv');\n    }\n\n    public function test_cannot_read_with_wrong_delimiter()\n    {\n        $import = new class implements WithCustomCsvSettings, ToArray\n        {\n            /**\n             * @return array\n             */\n            public function getCsvSettings(): array\n            {\n                return [\n                    'delimiter' => ',',\n                ];\n            }\n\n            /**\n             * @param  array  $array\n             */\n            public function array(array $array)\n            {\n                Assert::assertEquals([\n                    ['A1;B1'],\n                    ['A2;B2'],\n                ], $array);\n            }\n        };\n\n        $this->SUT->import($import, 'csv-with-other-delimiter.csv');\n    }\n}\n"
  },
  {
    "path": "tests/Concerns/WithCustomQuerySizeTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Concerns;\n\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\AfterQueueExportJob;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database\\Group;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database\\User;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\FromQueryWithCustomQuerySize;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\n\nclass WithCustomQuerySizeTest extends TestCase\n{\n    /**\n     * Setup the test environment.\n     */\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $this->loadLaravelMigrations(['--database' => 'testing']);\n        $this->loadMigrationsFrom(dirname(__DIR__) . '/Data/Stubs/Database/Migrations');\n        $this->withFactories(dirname(__DIR__) . '/Data/Stubs/Database/Factories');\n\n        factory(Group::class)->times(5)->create()->each(function ($group) {\n            $group->users()->attach(factory(User::class)->times(rand(1, 3))->create());\n        });\n\n        config()->set('excel.exports.chunk_size', 2);\n    }\n\n    public function test_can_export_with_custom_count()\n    {\n        $export = new FromQueryWithCustomQuerySize();\n\n        $export->queue('export-from-query-with-count.xlsx', null, 'Xlsx')->chain([\n            new AfterQueueExportJob(dirname(__DIR__) . '/Data/Disks/Local/export-from-query-with-count.xlsx'),\n        ]);\n\n        $actual = $this->readAsArray(dirname(__DIR__) . '/Data/Disks/Local/export-from-query-with-count.xlsx', 'Xlsx');\n\n        $this->assertCount(Group::count(), $actual);\n    }\n}\n"
  },
  {
    "path": "tests/Concerns/WithCustomStartCellTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Concerns;\n\nuse Illuminate\\Support\\Collection;\nuse Maatwebsite\\Excel\\Concerns\\FromCollection;\nuse Maatwebsite\\Excel\\Concerns\\WithCustomStartCell;\nuse Maatwebsite\\Excel\\Excel;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\n\nclass WithCustomStartCellTest extends TestCase\n{\n    /**\n     * @var Excel\n     */\n    protected $SUT;\n\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $this->SUT = $this->app->make(Excel::class);\n    }\n\n    public function test_can_store_collection_with_custom_start_cell()\n    {\n        $export = new class implements FromCollection, WithCustomStartCell\n        {\n            /**\n             * @return Collection\n             */\n            public function collection()\n            {\n                return collect([\n                    ['A1', 'B1'],\n                    ['A2', 'B2'],\n                ]);\n            }\n\n            /**\n             * @return string\n             */\n            public function startCell(): string\n            {\n                return 'B2';\n            }\n        };\n\n        $this->SUT->store($export, 'custom-start-cell.csv');\n\n        $contents = $this->readAsArray(__DIR__ . '/../Data/Disks/Local/custom-start-cell.csv', 'Csv');\n\n        $this->assertEquals([\n            [null, null, null],\n            [null, 'A1', 'B1'],\n            [null, 'A2', 'B2'],\n        ], $contents);\n    }\n}\n"
  },
  {
    "path": "tests/Concerns/WithCustomValueBinderTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Concerns;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Collection;\nuse Maatwebsite\\Excel\\Concerns\\Exportable;\nuse Maatwebsite\\Excel\\Concerns\\FromCollection;\nuse Maatwebsite\\Excel\\Concerns\\ToArray;\nuse Maatwebsite\\Excel\\Concerns\\WithCustomValueBinder;\nuse Maatwebsite\\Excel\\Excel;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\nuse PhpOffice\\PhpSpreadsheet\\Cell\\Cell;\nuse PhpOffice\\PhpSpreadsheet\\Cell\\DataType;\nuse PhpOffice\\PhpSpreadsheet\\Cell\\DefaultValueBinder;\nuse PhpOffice\\PhpSpreadsheet\\Shared\\Date;\nuse PhpOffice\\PhpSpreadsheet\\Style\\NumberFormat;\nuse PHPUnit\\Framework\\Assert;\n\nclass WithCustomValueBinderTest extends TestCase\n{\n    public function test_can_set_a_value_binder_on_export()\n    {\n        Carbon::setTestNow(new Carbon('2018-08-07 18:00:00'));\n\n        $export = new class extends DefaultValueBinder implements FromCollection, WithCustomValueBinder\n        {\n            use Exportable;\n\n            /**\n             * @return Collection\n             */\n            public function collection()\n            {\n                return collect([\n                    [Carbon::now(), '10%'],\n                ]);\n            }\n\n            /**\n             * {@inheritdoc}\n             */\n            public function bindValue(Cell $cell, $value)\n            {\n                // Handle percentage\n                if (preg_match('/^\\-?\\d*\\.?\\d*\\s?\\%$/', $value)) {\n                    $cell->setValueExplicit(\n                        (float) str_replace('%', '', $value) / 100,\n                        DataType::TYPE_NUMERIC\n                    );\n\n                    $cell\n                        ->getWorksheet()\n                        ->getStyle($cell->getCoordinate())\n                        ->getNumberFormat()\n                        ->setFormatCode(NumberFormat::FORMAT_PERCENTAGE_00);\n\n                    return true;\n                }\n\n                // Handle Carbon dates\n                if ($value instanceof Carbon) {\n                    $cell->setValueExplicit(\n                        Date::dateTimeToExcel($value),\n                        DataType::TYPE_NUMERIC\n                    );\n\n                    $cell->getWorksheet()\n                         ->getStyle($cell->getCoordinate())\n                         ->getNumberFormat()\n                         ->setFormatCode(NumberFormat::FORMAT_DATE_DATETIME);\n\n                    return true;\n                }\n\n                return parent::bindValue($cell, $value);\n            }\n        };\n\n        $export->store('custom-value-binder-export.xlsx');\n\n        $spreadsheet = $this->read(__DIR__ . '/../Data/Disks/Local/custom-value-binder-export.xlsx', 'Xlsx');\n        $sheet       = $spreadsheet->getActiveSheet();\n\n        // Check if the cell has the Excel date\n        $this->assertSame(Date::dateTimeToExcel(Carbon::now()), $sheet->getCell('A1')->getValue());\n\n        // Check if formatted as datetime\n        $this->assertEquals(NumberFormat::FORMAT_DATE_DATETIME, $sheet->getCell('A1')->getStyle()->getNumberFormat()->getFormatCode());\n\n        // Check if the cell has the converted percentage\n        $this->assertSame(0.1, $sheet->getCell('B1')->getValue());\n\n        // Check if formatted as percentage\n        $this->assertEquals(NumberFormat::FORMAT_PERCENTAGE_00, $sheet->getCell('B1')->getStyle()->getNumberFormat()->getFormatCode());\n    }\n\n    public function test_can_set_a_value_binder_on_import()\n    {\n        $import = new class extends DefaultValueBinder implements WithCustomValueBinder, ToArray\n        {\n            /**\n             * {@inheritdoc}\n             */\n            public function bindValue(Cell $cell, $value)\n            {\n                if ($cell->getCoordinate() === 'B2') {\n                    $cell->setValueExplicit($value, DataType::TYPE_STRING);\n\n                    return true;\n                }\n\n                if ($cell->getRow() === 3) {\n                    $date = Carbon::instance(Date::excelToDateTimeObject($value));\n                    $cell->setValueExplicit($date->toDateTimeString(), DataType::TYPE_STRING);\n\n                    return true;\n                }\n\n                return parent::bindValue($cell, $value);\n            }\n\n            /**\n             * @param  array  $array\n             */\n            public function array(array $array)\n            {\n                Assert::assertSame([\n                    [\n                        'col1',\n                        'col2',\n                    ],\n                    [\n                        1,\n                        '2', // Forced to be a string\n                    ],\n                    [\n                        '2018-08-06 18:31:46', // Convert Excel datetime to datetime strings\n                        '2018-08-07 00:00:00', // Convert Excel date to datetime strings\n                    ],\n                ], $array);\n            }\n        };\n\n        $this->app->make(Excel::class)->import($import, 'value-binder-import.xlsx');\n    }\n}\n"
  },
  {
    "path": "tests/Concerns/WithDefaultStylesTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Concerns;\n\nuse Maatwebsite\\Excel\\Concerns\\Exportable;\nuse Maatwebsite\\Excel\\Concerns\\FromArray;\nuse Maatwebsite\\Excel\\Concerns\\WithDefaultStyles;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\nuse PhpOffice\\PhpSpreadsheet\\Style\\Fill;\nuse PhpOffice\\PhpSpreadsheet\\Style\\Style;\n\nclass WithDefaultStylesTest extends TestCase\n{\n    public function test_can_configure_default_styles()\n    {\n        $export = new class implements FromArray, WithDefaultStyles\n        {\n            use Exportable;\n\n            public function defaultStyles(Style $defaultStyle)\n            {\n                return [\n                    'fill' => [\n                        'fillType'   => Fill::FILL_SOLID,\n                        'startColor' => ['argb' => 'fff2f2f2'],\n                    ],\n                ];\n            }\n\n            public function array(): array\n            {\n                return [\n                    ['A1', 'B1', 'C1'],\n                    ['A2', 'B2', 'C2'],\n                ];\n            }\n        };\n\n        $export->store('with-default-styles.xlsx');\n\n        $spreadsheet = $this->read(__DIR__ . '/../Data/Disks/Local/with-default-styles.xlsx', 'Xlsx');\n        $sheet       = $spreadsheet->getDefaultStyle();\n\n        $this->assertEquals(Fill::FILL_SOLID, $sheet->getFill()->getFillType());\n        $this->assertEquals('fff2f2f2', $sheet->getFill()->getStartColor()->getARGB());\n    }\n}\n"
  },
  {
    "path": "tests/Concerns/WithEventsTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Concerns;\n\nuse Illuminate\\Foundation\\Testing\\WithFaker;\nuse Illuminate\\Support\\Str;\nuse Maatwebsite\\Excel\\Concerns\\Exportable;\nuse Maatwebsite\\Excel\\Events\\AfterBatch;\nuse Maatwebsite\\Excel\\Events\\AfterChunk;\nuse Maatwebsite\\Excel\\Events\\AfterImport;\nuse Maatwebsite\\Excel\\Events\\AfterSheet;\nuse Maatwebsite\\Excel\\Events\\BeforeExport;\nuse Maatwebsite\\Excel\\Events\\BeforeImport;\nuse Maatwebsite\\Excel\\Events\\BeforeSheet;\nuse Maatwebsite\\Excel\\Events\\BeforeWriting;\nuse Maatwebsite\\Excel\\Excel;\nuse Maatwebsite\\Excel\\Reader;\nuse Maatwebsite\\Excel\\Sheet;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\BeforeExportListener;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\CustomConcern;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\CustomSheetConcern;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database\\User;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\ExportWithEvents;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\ExportWithEventsChunks;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\ImportWithEvents;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\ImportWithEventsChunksAndBatches;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\nuse Maatwebsite\\Excel\\Writer;\nuse Symfony\\Component\\HttpFoundation\\BinaryFileResponse;\n\nclass WithEventsTest extends TestCase\n{\n    use WithFaker;\n\n    public function test_export_events_get_called()\n    {\n        $event = new ExportWithEvents();\n\n        $eventsTriggered = 0;\n\n        $event->beforeExport = function ($event) use (&$eventsTriggered) {\n            $this->assertInstanceOf(BeforeExport::class, $event);\n            $this->assertInstanceOf(Writer::class, $event->getWriter());\n            $eventsTriggered++;\n        };\n\n        $event->beforeWriting = function ($event) use (&$eventsTriggered) {\n            $this->assertInstanceOf(BeforeWriting::class, $event);\n            $this->assertInstanceOf(Writer::class, $event->getWriter());\n            $eventsTriggered++;\n        };\n\n        $event->beforeSheet = function ($event) use (&$eventsTriggered) {\n            $this->assertInstanceOf(BeforeSheet::class, $event);\n            $this->assertInstanceOf(Sheet::class, $event->getSheet());\n            $eventsTriggered++;\n        };\n\n        $event->afterSheet = function ($event) use (&$eventsTriggered) {\n            $this->assertInstanceOf(AfterSheet::class, $event);\n            $this->assertInstanceOf(Sheet::class, $event->getSheet());\n            $eventsTriggered++;\n        };\n\n        $this->assertInstanceOf(BinaryFileResponse::class, $event->download('filename.xlsx'));\n        $this->assertEquals(4, $eventsTriggered);\n    }\n\n    public function test_import_events_get_called()\n    {\n        $import = new ImportWithEvents();\n\n        $eventsTriggered = 0;\n\n        $import->beforeImport = function ($event) use (&$eventsTriggered) {\n            $this->assertInstanceOf(BeforeImport::class, $event);\n            $this->assertInstanceOf(Reader::class, $event->getReader());\n            $eventsTriggered++;\n        };\n\n        $import->afterImport = function ($event) use (&$eventsTriggered) {\n            $this->assertInstanceOf(AfterImport::class, $event);\n            $this->assertInstanceOf(Reader::class, $event->getReader());\n            $eventsTriggered++;\n        };\n\n        $import->beforeSheet = function ($event) use (&$eventsTriggered) {\n            $this->assertInstanceOf(BeforeSheet::class, $event);\n            $this->assertInstanceOf(Sheet::class, $event->getSheet());\n            $eventsTriggered++;\n        };\n\n        $import->afterSheet = function ($event) use (&$eventsTriggered) {\n            $this->assertInstanceOf(AfterSheet::class, $event);\n            $this->assertInstanceOf(Sheet::class, $event->getSheet());\n            $eventsTriggered++;\n        };\n\n        $import->import('import.xlsx');\n        $this->assertEquals(4, $eventsTriggered);\n    }\n\n    public function test_import_chunked_events_get_called()\n    {\n        $import = new ImportWithEventsChunksAndBatches();\n\n        $beforeImport = 0;\n        $afterImport  = 0;\n        $beforeSheet  = 0;\n        $afterSheet   = 0;\n        $afterBatch   = 0;\n        $afterChunk   = 0;\n\n        $import->beforeImport = function (BeforeImport $event) use (&$beforeImport) {\n            $this->assertInstanceOf(Reader::class, $event->getReader());\n            // Ensure event is fired only once\n            $this->assertEquals(0, $beforeImport, 'Before import called twice');\n            $beforeImport++;\n        };\n\n        $import->afterImport = function (AfterImport $event) use (&$afterImport) {\n            $this->assertInstanceOf(Reader::class, $event->getReader());\n            $this->assertEquals(0, $afterImport, 'After import called twice');\n            $afterImport++;\n        };\n\n        $import->beforeSheet = function (BeforeSheet $event) use (&$beforeSheet) {\n            $this->assertInstanceOf(Sheet::class, $event->getSheet());\n            $beforeSheet++;\n        };\n\n        $import->afterSheet = function (AfterSheet $event) use (&$afterSheet) {\n            $this->assertInstanceOf(Sheet::class, $event->getSheet());\n            $afterSheet++;\n        };\n\n        $import->afterBatch = function (AfterBatch $event) use ($import, &$afterBatch) {\n            $this->assertEquals(\n                $import->batchSize(),\n                $event->getBatchSize(),\n                'Wrong Batch size'\n            );\n            $this->assertEquals(\n                $afterBatch * $import->batchSize() + 1,\n                $event->getStartRow(),\n                'Wrong batch start row');\n            $afterBatch++;\n        };\n\n        $import->afterChunk = function (AfterChunk $event) use ($import, &$afterChunk) {\n            $this->assertEquals(\n                $event->getStartRow(),\n                $afterChunk * $import->chunkSize() + 1,\n                'Wrong chunk start row');\n            $afterChunk++;\n        };\n\n        $import->import('import-batches.xlsx');\n        $this->assertEquals(10, $afterSheet);\n        $this->assertEquals(10, $beforeSheet);\n        $this->assertEquals(50, $afterBatch);\n        $this->assertEquals(10, $afterChunk);\n    }\n\n    public function test_can_have_invokable_class_as_listener()\n    {\n        $event = new ExportWithEvents();\n\n        $event->beforeExport = new BeforeExportListener(function ($event) {\n            $this->assertInstanceOf(BeforeExport::class, $event);\n            $this->assertInstanceOf(Writer::class, $event->getWriter());\n        });\n\n        $this->assertInstanceOf(BinaryFileResponse::class, $event->download('filename.xlsx'));\n    }\n\n    public function test_can_have_global_event_listeners()\n    {\n        $event = new class\n        {\n            use Exportable;\n        };\n\n        $beforeExport = false;\n        Writer::listen(BeforeExport::class, function () use (&$beforeExport) {\n            $beforeExport = true;\n        });\n\n        $beforeWriting = false;\n        Writer::listen(BeforeWriting::class, function () use (&$beforeWriting) {\n            $beforeWriting = true;\n        });\n\n        $beforeSheet = false;\n        Sheet::listen(BeforeSheet::class, function () use (&$beforeSheet) {\n            $beforeSheet = true;\n        });\n\n        $afterSheet = false;\n        Sheet::listen(AfterSheet::class, function () use (&$afterSheet) {\n            $afterSheet = true;\n        });\n\n        $this->assertInstanceOf(BinaryFileResponse::class, $event->download('filename.xlsx'));\n\n        $this->assertTrue($beforeExport, 'Before export event not triggered');\n        $this->assertTrue($beforeWriting, 'Before writing event not triggered');\n        $this->assertTrue($beforeSheet, 'Before sheet event not triggered');\n        $this->assertTrue($afterSheet, 'After sheet event not triggered');\n    }\n\n    public function test_can_have_custom_concern_handlers()\n    {\n        // Add a custom concern handler for the given concern.\n        Excel::extend(CustomConcern::class, function (CustomConcern $exportable, Writer $writer) {\n            $writer->getSheetByIndex(0)->append(\n                $exportable->custom()\n            );\n        });\n\n        $exportWithConcern = new class implements CustomConcern\n        {\n            use Exportable;\n\n            public function custom()\n            {\n                return [\n                    ['a', 'b'],\n                ];\n            }\n        };\n\n        $exportWithConcern->store('with-custom-concern.xlsx');\n        $actual = $this->readAsArray(__DIR__ . '/../Data/Disks/Local/with-custom-concern.xlsx', 'Xlsx');\n        $this->assertEquals([\n            ['a', 'b'],\n        ], $actual);\n\n        $exportWithoutConcern = new class\n        {\n            use Exportable;\n        };\n\n        $exportWithoutConcern->store('without-custom-concern.xlsx');\n        $actual = $this->readAsArray(__DIR__ . '/../Data/Disks/Local/without-custom-concern.xlsx', 'Xlsx');\n\n        $this->assertEquals([[null]], $actual);\n    }\n\n    public function test_can_have_custom_sheet_concern_handlers()\n    {\n        // Add a custom concern handler for the given concern.\n        Excel::extend(CustomSheetConcern::class, function (CustomSheetConcern $exportable, Sheet $sheet) {\n            $sheet->append(\n                $exportable->custom()\n            );\n        }, AfterSheet::class);\n\n        $exportWithConcern = new class implements CustomSheetConcern\n        {\n            use Exportable;\n\n            public function custom()\n            {\n                return [\n                    ['c', 'd'],\n                ];\n            }\n        };\n\n        $exportWithConcern->store('with-custom-concern.xlsx');\n        $actual = $this->readAsArray(__DIR__ . '/../Data/Disks/Local/with-custom-concern.xlsx', 'Xlsx');\n        $this->assertEquals([\n            ['c', 'd'],\n        ], $actual);\n\n        $exportWithoutConcern = new class\n        {\n            use Exportable;\n        };\n\n        $exportWithoutConcern->store('without-custom-concern.xlsx');\n        $actual = $this->readAsArray(__DIR__ . '/../Data/Disks/Local/without-custom-concern.xlsx', 'Xlsx');\n\n        $this->assertEquals([[null]], $actual);\n    }\n\n    public function test_export_chunked_events_get_called()\n    {\n        $this->loadLaravelMigrations(['--database' => 'testing']);\n\n        User::query()->truncate();\n\n        User::query()->create([\n            'name'           => $this->faker->name,\n            'email'          => $this->faker->unique()->safeEmail,\n            'password'       => '$2y$10$TKh8H1.PfQx37YgCzwiKb.KjNyWgaHb9cbcoQgdIVFlYg7B77UdFm', // secret\n            'remember_token' => Str::random(10),\n        ]);\n\n        User::query()->create([\n            'name'           => $this->faker->name,\n            'email'          => $this->faker->unique()->safeEmail,\n            'password'       => '$2y$10$TKh8H1.PfQx37YgCzwiKb.KjNyWgaHb9cbcoQgdIVFlYg7B77UdFm', // secret\n            'remember_token' => Str::random(10),\n        ]);\n\n        $export = new ExportWithEventsChunks();\n        $export->queue('filename.xlsx');\n\n        // Chunk size is 1, so we expect 2 chunks to be executed with a total of 2 users\n        $this->assertEquals(2, ExportWithEventsChunks::$calledEvent);\n    }\n}\n"
  },
  {
    "path": "tests/Concerns/WithFormatDataTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Concerns;\n\nuse Illuminate\\Support\\Collection;\nuse Maatwebsite\\Excel\\Concerns\\Importable;\nuse Maatwebsite\\Excel\\Concerns\\SkipsEmptyRows;\nuse Maatwebsite\\Excel\\Concerns\\ToArray;\nuse Maatwebsite\\Excel\\Concerns\\ToCollection;\nuse Maatwebsite\\Excel\\Concerns\\ToModel;\nuse Maatwebsite\\Excel\\Concerns\\WithFormatData;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\nuse PHPUnit\\Framework\\Assert;\n\nclass WithFormatDataTest extends TestCase\n{\n    public function test_by_default_import_to_array()\n    {\n        $import = new class implements ToArray\n        {\n            use Importable;\n\n            public $called = false;\n\n            /**\n             * @param  array  $array\n             */\n            public function array(array $array)\n            {\n                $this->called = true;\n\n                Assert::assertSame(44328, $array[0][0]);\n            }\n        };\n\n        $import->import('import-format-data.xlsx');\n\n        $this->assertTrue($import->called);\n    }\n\n    public function test_can_import_to_array_with_format_data()\n    {\n        config()->set('excel.imports.read_only', false);\n        $import = new class implements ToArray, WithFormatData\n        {\n            use Importable;\n\n            public $called = false;\n\n            /**\n             * @param  array  $array\n             */\n            public function array(array $array)\n            {\n                $this->called = true;\n\n                Assert::assertSame('5/12/2021', $array[0][0]);\n            }\n        };\n\n        $import->import('import-format-data.xlsx');\n\n        $this->assertTrue($import->called);\n    }\n\n    public function test_can_import_to_array_with_format_data_and_skips_empty_rows()\n    {\n        config()->set('excel.imports.read_only', false);\n        $import = new class implements ToArray, WithFormatData, SkipsEmptyRows\n        {\n            use Importable;\n\n            public $called = false;\n\n            /**\n             * @param  array  $array\n             */\n            public function array(array $array)\n            {\n                $this->called = true;\n\n                Assert::assertSame('5/12/2021', $array[0][0]);\n            }\n        };\n\n        $import->import('import-format-data.xlsx');\n\n        $this->assertTrue($import->called);\n    }\n\n    public function test_by_default_import_to_collection()\n    {\n        $import = new class implements ToCollection\n        {\n            use Importable;\n\n            public $called = false;\n\n            /**\n             * @param  array  $row\n             * @return Model|null\n             */\n            public function collection(collection $collection)\n            {\n                $this->called = true;\n\n                Assert::assertSame(44328, $collection[0][0]);\n\n                return null;\n            }\n        };\n\n        $import->import('import-format-data.xlsx');\n\n        $this->assertTrue($import->called);\n    }\n\n    public function test_can_import_to_collection_with_format_data()\n    {\n        config()->set('excel.imports.read_only', false);\n        $import = new class implements ToCollection, WithFormatData\n        {\n            use Importable;\n\n            public $called = false;\n\n            /**\n             * @param  array  $row\n             * @return Model|null\n             */\n            public function collection(collection $collection)\n            {\n                $this->called = true;\n\n                Assert::assertSame('5/12/2021', $collection[0][0]);\n\n                return null;\n            }\n        };\n\n        $import->import('import-format-data.xlsx');\n\n        $this->assertTrue($import->called);\n    }\n\n    public function test_by_default_import_to_model()\n    {\n        $import = new class implements ToModel\n        {\n            use Importable;\n\n            public $called = false;\n\n            /**\n             * @param  array  $row\n             * @return Model|null\n             */\n            public function model(array $row)\n            {\n                $this->called = true;\n\n                Assert::assertSame(44328, $row[0]);\n\n                return null;\n            }\n        };\n\n        $import->import('import-format-data.xlsx');\n\n        $this->assertTrue($import->called);\n    }\n\n    public function test_can_import_to_model_with_format_data()\n    {\n        config()->set('excel.imports.read_only', false);\n        $import = new class implements ToModel, WithFormatData\n        {\n            use Importable;\n\n            public $called = false;\n\n            /**\n             * @param  array  $row\n             * @return Model|null\n             */\n            public function model(array $row)\n            {\n                $this->called = true;\n\n                Assert::assertSame('5/12/2021', $row[0]);\n\n                return null;\n            }\n        };\n\n        $import->import('import-format-data.xlsx');\n\n        $this->assertTrue($import->called);\n    }\n}\n"
  },
  {
    "path": "tests/Concerns/WithGroupedHeadingRowTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Concerns;\n\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Support\\Collection;\nuse Maatwebsite\\Excel\\Concerns\\Importable;\nuse Maatwebsite\\Excel\\Concerns\\OnEachRow;\nuse Maatwebsite\\Excel\\Concerns\\ToArray;\nuse Maatwebsite\\Excel\\Concerns\\ToCollection;\nuse Maatwebsite\\Excel\\Concerns\\ToModel;\nuse Maatwebsite\\Excel\\Concerns\\WithGroupedHeadingRow;\nuse Maatwebsite\\Excel\\Row;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database\\User;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\nuse PHPUnit\\Framework\\Assert;\n\nclass WithGroupedHeadingRowTest extends TestCase\n{\n    /**\n     * Setup the test environment.\n     */\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $this->loadLaravelMigrations(['--database' => 'testing']);\n        $this->loadMigrationsFrom(dirname(__DIR__) . '/Data/Stubs/Database/Migrations');\n    }\n\n    public function test_can_import_to_array_with_grouped_headers()\n    {\n        $import = new class implements ToArray, WithGroupedHeadingRow\n        {\n            use Importable;\n\n            /**\n             * @param  array  $array\n             */\n            public function array(array $array)\n            {\n                Assert::assertEquals([\n                    [\n                        'name'    => 'Patrick Brouwers',\n                        'email'   => 'patrick@maatwebsite.nl',\n                        'options' => [\n                            'laravel',\n                            'excel',\n                        ],\n                    ],\n                ], $array);\n            }\n        };\n\n        $import->import('import-users-with-grouped-headers.xlsx');\n    }\n\n    public function test_can_import_oneachrow_with_grouped_headers()\n    {\n        $import = new class implements OnEachRow, WithGroupedHeadingRow\n        {\n            use Importable;\n\n            /**\n             * @param  \\Maatwebsite\\Excel\\Row  $row\n             * @return void\n             */\n            public function onRow(Row $row)\n            {\n                Assert::assertEquals(\n                    [\n                        'name'    => 'Patrick Brouwers',\n                        'email'   => 'patrick@maatwebsite.nl',\n                        'options' => [\n                            'laravel',\n                            'excel',\n                        ],\n                    ], $row->toArray());\n            }\n        };\n\n        $import->import('import-users-with-grouped-headers.xlsx');\n    }\n\n    public function test_can_import_to_collection_with_grouped_headers()\n    {\n        $import = new class implements ToCollection, WithGroupedHeadingRow\n        {\n            use Importable;\n\n            public $called = false;\n\n            /**\n             * @param  Collection  $collection\n             */\n            public function collection(Collection $collection)\n            {\n                $this->called = true;\n\n                Assert::assertEquals([\n                    [\n                        'name'    => 'Patrick Brouwers',\n                        'email'   => 'patrick@maatwebsite.nl',\n                        'options' => [\n                            'laravel',\n                            'excel',\n                        ],\n                    ],\n                ], $collection->toArray());\n            }\n        };\n\n        $import->import('import-users-with-grouped-headers.xlsx');\n\n        $this->assertTrue($import->called);\n    }\n\n    public function test_can_import_each_row_to_model_with_grouped_headers()\n    {\n        $import = new class implements ToModel, WithGroupedHeadingRow\n        {\n            use Importable;\n\n            /**\n             * @param  array  $row\n             * @return Model\n             */\n            public function model(array $row): Model\n            {\n                return new User([\n                    'name'     => $row['name'],\n                    'email'    => $row['email'],\n                    'password' => 'secret',\n                    'options'  => $row['options'],\n                ]);\n            }\n        };\n\n        $import->import('import-users-with-grouped-headers.xlsx');\n\n        $this->assertDatabaseHas('users', [\n            'name'    => 'Patrick Brouwers',\n            'email'   => 'patrick@maatwebsite.nl',\n            'options' => '[\"laravel\",\"excel\"]',\n        ]);\n    }\n}\n"
  },
  {
    "path": "tests/Concerns/WithHeadingRowTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Concerns;\n\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Support\\Collection;\nuse Maatwebsite\\Excel\\Concerns\\Importable;\nuse Maatwebsite\\Excel\\Concerns\\ToArray;\nuse Maatwebsite\\Excel\\Concerns\\ToCollection;\nuse Maatwebsite\\Excel\\Concerns\\ToModel;\nuse Maatwebsite\\Excel\\Concerns\\WithHeadingRow;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database\\User;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\nuse PHPUnit\\Framework\\Assert;\n\nclass WithHeadingRowTest extends TestCase\n{\n    /**\n     * Setup the test environment.\n     */\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $this->loadLaravelMigrations(['--database' => 'testing']);\n    }\n\n    public function test_can_import_each_row_to_model_with_heading_row()\n    {\n        $import = new class implements ToModel, WithHeadingRow\n        {\n            use Importable;\n\n            /**\n             * @param  array  $row\n             * @return Model\n             */\n            public function model(array $row): Model\n            {\n                return new User([\n                    'name'     => $row['name'],\n                    'email'    => $row['email'],\n                    'password' => 'secret',\n                ]);\n            }\n        };\n\n        $import->import('import-users-with-headings.xlsx');\n\n        $this->assertDatabaseHas('users', [\n            'name'  => 'Patrick Brouwers',\n            'email' => 'patrick@maatwebsite.nl',\n        ]);\n\n        $this->assertDatabaseHas('users', [\n            'name'  => 'Taylor Otwell',\n            'email' => 'taylor@laravel.com',\n        ]);\n    }\n\n    public function test_can_import_each_row_to_model_with_different_heading_row()\n    {\n        $import = new class implements ToModel, WithHeadingRow\n        {\n            use Importable;\n\n            /**\n             * @param  array  $row\n             * @return Model\n             */\n            public function model(array $row): Model\n            {\n                return new User([\n                    'name'     => $row['name'],\n                    'email'    => $row['email'],\n                    'password' => 'secret',\n                ]);\n            }\n\n            /**\n             * @return int\n             */\n            public function headingRow(): int\n            {\n                return 4;\n            }\n        };\n\n        $import->import('import-users-with-different-heading-row.xlsx');\n\n        $this->assertDatabaseHas('users', [\n            'name'  => 'Patrick Brouwers',\n            'email' => 'patrick@maatwebsite.nl',\n        ]);\n\n        $this->assertDatabaseHas('users', [\n            'name'  => 'Taylor Otwell',\n            'email' => 'taylor@laravel.com',\n        ]);\n    }\n\n    public function test_can_import_to_array_with_heading_row()\n    {\n        $import = new class implements ToArray, WithHeadingRow\n        {\n            use Importable;\n\n            /**\n             * @param  array  $array\n             */\n            public function array(array $array)\n            {\n                Assert::assertEquals([\n                    [\n                        'name'  => 'Patrick Brouwers',\n                        'email' => 'patrick@maatwebsite.nl',\n                    ],\n                    [\n                        'name'  => 'Taylor Otwell',\n                        'email' => 'taylor@laravel.com',\n                    ],\n                ], $array);\n            }\n        };\n\n        $import->import('import-users-with-headings.xlsx');\n    }\n\n    public function test_can_import_empty_rows_with_header()\n    {\n        $import = new class() implements ToArray, WithHeadingRow\n        {\n            use Importable;\n\n            /**\n             * @param  array  $array\n             */\n            public function array(array $array)\n            {\n                Assert::assertEmpty($array);\n            }\n        };\n\n        $import->import('import-empty-users-with-headings.xlsx');\n    }\n\n    public function test_can_import_empty_models_with_header()\n    {\n        $import = new class() implements ToModel, WithHeadingRow\n        {\n            use Importable;\n\n            /**\n             * @param  array  $row\n             * @return Model\n             */\n            public function model(array $row): Model\n            {\n                return new User([\n                    'name'     => $row['name'],\n                    'email'    => $row['email'],\n                    'password' => 'secret',\n                ]);\n            }\n        };\n\n        $import->import('import-empty-users-with-headings.xlsx');\n        $this->assertEmpty(User::all());\n    }\n\n    public function test_can_cast_empty_headers_to_indexed_int()\n    {\n        $import = new class() implements ToCollection, WithHeadingRow\n        {\n            use Importable;\n\n            public $called = false;\n\n            public function collection(Collection $collection)\n            {\n                $this->called = true;\n\n                Assert::assertEquals([\n                    0 => 0,\n                    1 => 'email',\n                    2 => 'status',\n                    3 => 3,\n                ], $collection->first()->keys()->toArray());\n            }\n        };\n\n        $import->import('import-users-with-mixed-headings.xlsx');\n        $this->assertTrue($import->called);\n    }\n}\n"
  },
  {
    "path": "tests/Concerns/WithHeadingsTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Concerns;\n\nuse Illuminate\\Support\\Collection;\nuse Maatwebsite\\Excel\\Concerns\\Exportable;\nuse Maatwebsite\\Excel\\Concerns\\FromCollection;\nuse Maatwebsite\\Excel\\Concerns\\WithCustomStartCell;\nuse Maatwebsite\\Excel\\Concerns\\WithHeadings;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\n\nclass WithHeadingsTest extends TestCase\n{\n    public function test_can_export_from_collection_with_heading_row()\n    {\n        $export = new class implements FromCollection, WithHeadings\n        {\n            use Exportable;\n\n            /**\n             * @return Collection\n             */\n            public function collection()\n            {\n                return collect([\n                    ['A1', 'B1', 'C1'],\n                    ['A2', 'B2', 'C2'],\n                ]);\n            }\n\n            /**\n             * @return array\n             */\n            public function headings(): array\n            {\n                return ['A', 'B', 'C'];\n            }\n        };\n\n        $response = $export->store('with-heading-store.xlsx');\n\n        $this->assertTrue($response);\n\n        $actual = $this->readAsArray(__DIR__ . '/../Data/Disks/Local/with-heading-store.xlsx', 'Xlsx');\n\n        $expected = [\n            ['A', 'B', 'C'],\n            ['A1', 'B1', 'C1'],\n            ['A2', 'B2', 'C2'],\n        ];\n\n        $this->assertEquals($expected, $actual);\n    }\n\n    public function test_can_export_from_collection_with_multiple_heading_rows()\n    {\n        $export = new class implements FromCollection, WithHeadings\n        {\n            use Exportable;\n\n            /**\n             * @return Collection\n             */\n            public function collection()\n            {\n                return collect([\n                    ['A1', 'B1', 'C1'],\n                    ['A2', 'B2', 'C2'],\n                ]);\n            }\n\n            /**\n             * @return array\n             */\n            public function headings(): array\n            {\n                return [\n                    ['A', 'B', 'C'],\n                    ['Aa', 'Bb', 'Cc'],\n                ];\n            }\n        };\n\n        $response = $export->store('with-heading-store.xlsx');\n\n        $this->assertTrue($response);\n\n        $actual = $this->readAsArray(__DIR__ . '/../Data/Disks/Local/with-heading-store.xlsx', 'Xlsx');\n\n        $expected = [\n            ['A', 'B', 'C'],\n            ['Aa', 'Bb', 'Cc'],\n            ['A1', 'B1', 'C1'],\n            ['A2', 'B2', 'C2'],\n        ];\n\n        $this->assertEquals($expected, $actual);\n    }\n\n    public function test_can_export_from_collection_with_heading_row_with_custom_start_cell()\n    {\n        $export = new class implements FromCollection, WithHeadings, WithCustomStartCell\n        {\n            use Exportable;\n\n            /**\n             * @return Collection\n             */\n            public function collection()\n            {\n                return collect([\n                    ['A1', 'B1', 'C1'],\n                    ['A2', 'B2', 'C2'],\n                ]);\n            }\n\n            /**\n             * @return array\n             */\n            public function headings(): array\n            {\n                return ['A', 'B', 'C'];\n            }\n\n            /**\n             * @return string\n             */\n            public function startCell(): string\n            {\n                return 'B2';\n            }\n        };\n\n        $response = $export->store('with-heading-store.xlsx');\n\n        $this->assertTrue($response);\n\n        $actual = $this->readAsArray(__DIR__ . '/../Data/Disks/Local/with-heading-store.xlsx', 'Xlsx');\n\n        $expected = [\n            [null, null, null, null],\n            [null, 'A', 'B', 'C'],\n            [null, 'A1', 'B1', 'C1'],\n            [null, 'A2', 'B2', 'C2'],\n        ];\n\n        $this->assertEquals($expected, $actual);\n    }\n}\n"
  },
  {
    "path": "tests/Concerns/WithLimitTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Concerns;\n\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Maatwebsite\\Excel\\Concerns\\Importable;\nuse Maatwebsite\\Excel\\Concerns\\ToArray;\nuse Maatwebsite\\Excel\\Concerns\\ToModel;\nuse Maatwebsite\\Excel\\Concerns\\WithHeadingRow;\nuse Maatwebsite\\Excel\\Concerns\\WithLimit;\nuse Maatwebsite\\Excel\\Concerns\\WithStartRow;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database\\User;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\nuse PHPUnit\\Framework\\Assert;\n\nclass WithLimitTest extends TestCase\n{\n    /**\n     * Setup the test environment.\n     */\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $this->loadLaravelMigrations(['--database' => 'testing']);\n    }\n\n    public function test_can_import_a_limited_section_of_rows_to_model_with_different_start_row()\n    {\n        $import = new class implements ToModel, WithStartRow, WithLimit\n        {\n            use Importable;\n\n            /**\n             * @param  array  $row\n             * @return Model\n             */\n            public function model(array $row): Model\n            {\n                return new User([\n                    'name'     => $row[0],\n                    'email'    => $row[1],\n                    'password' => 'secret',\n                ]);\n            }\n\n            /**\n             * @return int\n             */\n            public function startRow(): int\n            {\n                return 5;\n            }\n\n            /**\n             * @return int\n             */\n            public function limit(): int\n            {\n                return 1;\n            }\n        };\n\n        $import->import('import-users-with-different-heading-row.xlsx');\n\n        $this->assertDatabaseHas('users', [\n            'name'  => 'Patrick Brouwers',\n            'email' => 'patrick@maatwebsite.nl',\n        ]);\n\n        $this->assertDatabaseMissing('users', [\n            'name'  => 'Taylor Otwell',\n            'email' => 'taylor@laravel.com',\n        ]);\n    }\n\n    public function test_can_import_to_array_with_limit()\n    {\n        $import = new class implements ToArray, WithLimit\n        {\n            use Importable;\n\n            /**\n             * @param  array  $array\n             */\n            public function array(array $array)\n            {\n                Assert::assertEquals([\n                    [\n                        'Patrick Brouwers',\n                        'patrick@maatwebsite.nl',\n                    ],\n                ], $array);\n            }\n\n            /**\n             * @return int\n             */\n            public function limit(): int\n            {\n                return 1;\n            }\n        };\n\n        $import->import('import-users.xlsx');\n    }\n\n    public function test_can_import_single_with_heading_row()\n    {\n        $import = new class implements ToArray, WithLimit, WithHeadingRow\n        {\n            use Importable;\n\n            /**\n             * @param  array  $array\n             */\n            public function array(array $array)\n            {\n                Assert::assertEquals([\n                    [\n                        'name'  => 'Patrick Brouwers',\n                        'email' => 'patrick@maatwebsite.nl',\n                    ],\n                ], $array);\n            }\n\n            /**\n             * @return int\n             */\n            public function limit(): int\n            {\n                return 1;\n            }\n        };\n\n        $import->import('import-users-with-headings.xlsx');\n    }\n\n    public function test_can_import_multiple_with_heading_row()\n    {\n        $import = new class implements ToArray, WithLimit, WithHeadingRow\n        {\n            use Importable;\n\n            /**\n             * @param  array  $array\n             */\n            public function array(array $array)\n            {\n                Assert::assertEquals([\n                    [\n                        'name'  => 'Patrick Brouwers',\n                        'email' => 'patrick@maatwebsite.nl',\n                    ],\n                    [\n                        'name'  => 'Taylor Otwell',\n                        'email' => 'taylor@laravel.com',\n                    ],\n                ], $array);\n            }\n\n            /**\n             * @return int\n             */\n            public function limit(): int\n            {\n                return 2;\n            }\n        };\n\n        $import->import('import-users-with-headings.xlsx');\n    }\n\n    public function test_can_set_limit_bigger_than_row_size()\n    {\n        $import = new class implements ToArray, WithLimit\n        {\n            use Importable;\n\n            /**\n             * @param  array  $array\n             */\n            public function array(array $array)\n            {\n                Assert::assertCount(2, $array);\n            }\n\n            /**\n             * @return int\n             */\n            public function limit(): int\n            {\n                return 10;\n            }\n        };\n\n        $import->import('import-users.xlsx');\n    }\n}\n"
  },
  {
    "path": "tests/Concerns/WithMappedCellsTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Concerns;\n\nuse Illuminate\\Support\\Str;\nuse Maatwebsite\\Excel\\Concerns\\Importable;\nuse Maatwebsite\\Excel\\Concerns\\ToArray;\nuse Maatwebsite\\Excel\\Concerns\\ToModel;\nuse Maatwebsite\\Excel\\Concerns\\WithMappedCells;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database\\User;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\nuse PHPUnit\\Framework\\Assert;\n\nclass WithMappedCellsTest extends TestCase\n{\n    /**\n     * Setup the test environment.\n     */\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $this->loadLaravelMigrations(['--database' => 'testing']);\n    }\n\n    public function test_can_import_with_references_to_cells()\n    {\n        $import = new class implements WithMappedCells, ToArray\n        {\n            use Importable;\n\n            /**\n             * @return array\n             */\n            public function mapping(): array\n            {\n                return [\n                    'name'  => 'B1',\n                    'email' => 'B2',\n                ];\n            }\n\n            /**\n             * @param  array  $array\n             */\n            public function array(array $array)\n            {\n                Assert::assertEquals([\n                    'name'  => 'Patrick Brouwers',\n                    'email' => 'patrick@maatwebsite.nl',\n                ], $array);\n            }\n        };\n\n        $import->import('mapped-import.xlsx');\n    }\n\n    public function test_can_import_with_nested_references_to_cells()\n    {\n        $import = new class implements WithMappedCells, ToArray\n        {\n            use Importable;\n\n            /**\n             * @return array\n             */\n            public function mapping(): array\n            {\n                return [\n                    [\n                        'name'  => 'B1',\n                        'email' => 'B2',\n                    ],\n                    [\n                        'name'  => 'D1',\n                        'email' => 'D2',\n                    ],\n                ];\n            }\n\n            /**\n             * @param  array  $array\n             */\n            public function array(array $array)\n            {\n                Assert::assertEquals([\n                    [\n                        'name'  => 'Patrick Brouwers',\n                        'email' => 'patrick@maatwebsite.nl',\n                    ],\n                    [\n                        'name'  => 'Typingbeaver',\n                        'email' => 'typingbeaver@mailbox.org',\n                    ],\n                ], $array);\n            }\n        };\n\n        $import->import('mapped-import.xlsx');\n    }\n\n    public function test_can_import_with_references_to_cells_to_model()\n    {\n        $import = new class implements WithMappedCells, ToModel\n        {\n            use Importable;\n\n            /**\n             * @return array\n             */\n            public function mapping(): array\n            {\n                return [\n                    'name'  => 'B1',\n                    'email' => 'B2',\n                ];\n            }\n\n            /**\n             * @param  array  $array\n             * @return User\n             */\n            public function model(array $array)\n            {\n                Assert::assertEquals([\n                    'name'  => 'Patrick Brouwers',\n                    'email' => 'patrick@maatwebsite.nl',\n                ], $array);\n\n                $array['password'] = Str::random();\n\n                return new User($array);\n            }\n        };\n\n        $import->import('mapped-import.xlsx');\n\n        $this->assertDatabaseHas('users', [\n            'name'  => 'Patrick Brouwers',\n            'email' => 'patrick@maatwebsite.nl',\n        ]);\n    }\n}\n"
  },
  {
    "path": "tests/Concerns/WithMappingTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Concerns;\n\nuse Maatwebsite\\Excel\\Concerns\\Exportable;\nuse Maatwebsite\\Excel\\Concerns\\FromArray;\nuse Maatwebsite\\Excel\\Concerns\\WithMapping;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\WithMappingExport;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\n\nclass WithMappingTest extends TestCase\n{\n    public function test_can_export_with_heading()\n    {\n        $export = new WithMappingExport();\n\n        $response = $export->store('with-mapping-store.xlsx');\n\n        $this->assertTrue($response);\n\n        $actual = $this->readAsArray(__DIR__ . '/../Data/Disks/Local/with-mapping-store.xlsx', 'Xlsx');\n\n        $expected = [\n            [\n                'mapped-A1',\n                'mapped-B1',\n                'mapped-C1',\n            ],\n            [\n                'mapped-A2',\n                'mapped-B2',\n                'mapped-C2',\n            ],\n        ];\n\n        $this->assertEquals($expected, $actual);\n    }\n\n    public function test_can_return_multiple_rows_in_map()\n    {\n        $export = new class implements FromArray, WithMapping\n        {\n            use Exportable;\n\n            /**\n             * @return array\n             */\n            public function array(): array\n            {\n                return [\n                    ['id' => 1],\n                    ['id' => 2],\n                    ['id' => 3],\n                ];\n            }\n\n            /**\n             * @param  mixed  $row\n             * @return array\n             */\n            public function map($row): array\n            {\n                return [\n                    [$row['id']],\n                    [$row['id']],\n                ];\n            }\n        };\n\n        $response = $export->store('with-mapping-store.xlsx');\n\n        $this->assertTrue($response);\n\n        $actual = $this->readAsArray(__DIR__ . '/../Data/Disks/Local/with-mapping-store.xlsx', 'Xlsx');\n\n        $this->assertCount(6, $actual);\n    }\n\n    public function test_json_array_columns_shouldnt_be_detected_as_multiple_rows()\n    {\n        $export = new class implements FromArray\n        {\n            use Exportable;\n\n            /**\n             * @return array\n             */\n            public function array(): array\n            {\n                return [\n                    ['id' => 1, 'json' => ['other_id' => 1]],\n                    ['id' => 2, 'json' => ['other_id' => 2]],\n                    ['id' => 3, 'json' => ['other_id' => 3]],\n                ];\n            }\n        };\n\n        $response = $export->store('with-mapping-store.xlsx');\n\n        $this->assertTrue($response);\n\n        $actual = $this->readAsArray(__DIR__ . '/../Data/Disks/Local/with-mapping-store.xlsx', 'Xlsx');\n\n        $this->assertCount(3, $actual);\n\n        $this->assertEquals([\n            [1, \\json_encode(['other_id' => 1])],\n            [2, \\json_encode(['other_id' => 2])],\n            [3, \\json_encode(['other_id' => 3])],\n        ], $actual);\n    }\n}\n"
  },
  {
    "path": "tests/Concerns/WithMultipleSheetsTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Concerns;\n\nuse Illuminate\\Support\\Collection;\nuse Maatwebsite\\Excel\\Concerns\\Exportable;\nuse Maatwebsite\\Excel\\Concerns\\Importable;\nuse Maatwebsite\\Excel\\Concerns\\SkipsUnknownSheets;\nuse Maatwebsite\\Excel\\Concerns\\ToArray;\nuse Maatwebsite\\Excel\\Concerns\\WithMultipleSheets;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database\\User;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\SheetForUsersFromView;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\SheetWith100Rows;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\nuse PHPUnit\\Framework\\Assert;\n\nclass WithMultipleSheetsTest extends TestCase\n{\n    /**\n     * Setup the test environment.\n     */\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $this->withFactories(__DIR__ . '/../Data/Stubs/Database/Factories');\n    }\n\n    public function test_can_export_with_multiple_sheets_using_collections()\n    {\n        $export = new class implements WithMultipleSheets\n        {\n            use Exportable;\n\n            /**\n             * @return SheetWith100Rows[]\n             */\n            public function sheets(): array\n            {\n                return [\n                    new SheetWith100Rows('A'),\n                    new SheetWith100Rows('B'),\n                    new SheetWith100Rows('C'),\n                ];\n            }\n        };\n\n        $export->store('from-view.xlsx');\n\n        $this->assertCount(100, $this->readAsArray(__DIR__ . '/../Data/Disks/Local/from-view.xlsx', 'Xlsx', 0));\n        $this->assertCount(100, $this->readAsArray(__DIR__ . '/../Data/Disks/Local/from-view.xlsx', 'Xlsx', 1));\n        $this->assertCount(100, $this->readAsArray(__DIR__ . '/../Data/Disks/Local/from-view.xlsx', 'Xlsx', 2));\n    }\n\n    public function test_can_export_multiple_sheets_from_view()\n    {\n        /** @var Collection|User[] $users */\n        $users = factory(User::class)->times(300)->make();\n\n        $export = new class($users) implements WithMultipleSheets\n        {\n            use Exportable;\n\n            /**\n             * @var Collection\n             */\n            protected $users;\n\n            /**\n             * @param  Collection  $users\n             */\n            public function __construct(Collection $users)\n            {\n                $this->users = $users;\n            }\n\n            /**\n             * @return SheetForUsersFromView[]\n             */\n            public function sheets(): array\n            {\n                return [\n                    new SheetForUsersFromView($this->users->forPage(1, 100)),\n                    new SheetForUsersFromView($this->users->forPage(2, 100)),\n                    new SheetForUsersFromView($this->users->forPage(3, 100)),\n                ];\n            }\n        };\n\n        $export->store('from-view.xlsx');\n\n        $this->assertCount(101, $this->readAsArray(__DIR__ . '/../Data/Disks/Local/from-view.xlsx', 'Xlsx', 0));\n        $this->assertCount(101, $this->readAsArray(__DIR__ . '/../Data/Disks/Local/from-view.xlsx', 'Xlsx', 1));\n        $this->assertCount(101, $this->readAsArray(__DIR__ . '/../Data/Disks/Local/from-view.xlsx', 'Xlsx', 2));\n    }\n\n    public function test_unknown_sheet_index_will_throw_sheet_not_found_exception()\n    {\n        $this->expectException(\\Maatwebsite\\Excel\\Exceptions\\SheetNotFoundException::class);\n        $this->expectExceptionMessage('Your requested sheet index: 9999 is out of bounds. The actual number of sheets is 2.');\n\n        $import = new class implements WithMultipleSheets\n        {\n            use Importable;\n\n            public function sheets(): array\n            {\n                return [\n                    9999 => new class {\n                    },\n                ];\n            }\n        };\n\n        $import->import('import-multiple-sheets.xlsx');\n    }\n\n    public function test_unknown_sheet_name_will_throw_sheet_not_found_exception()\n    {\n        $this->expectException(\\Maatwebsite\\Excel\\Exceptions\\SheetNotFoundException::class);\n        $this->expectExceptionMessage('Your requested sheet name [Some Random Sheet Name] is out of bounds.');\n\n        $import = new class implements WithMultipleSheets\n        {\n            use Importable;\n\n            public function sheets(): array\n            {\n                return [\n                    'Some Random Sheet Name' => new class {\n                    },\n                ];\n            }\n        };\n\n        $import->import('import-multiple-sheets.xlsx');\n    }\n\n    public function test_unknown_sheet_name_can_be_ignored()\n    {\n        $import = new class implements WithMultipleSheets, SkipsUnknownSheets\n        {\n            use Importable;\n\n            public $unknown;\n\n            public function sheets(): array\n            {\n                return [\n                    'Some Random Sheet Name' => new class {\n                    },\n                ];\n            }\n\n            /**\n             * @param  string|int  $sheetName\n             */\n            public function onUnknownSheet($sheetName)\n            {\n                $this->unknown = $sheetName;\n            }\n        };\n\n        $import->import('import-multiple-sheets.xlsx');\n\n        $this->assertEquals('Some Random Sheet Name', $import->unknown);\n    }\n\n    public function test_unknown_sheet_indices_can_be_ignored_per_name()\n    {\n        $import = new class implements WithMultipleSheets\n        {\n            use Importable;\n\n            public function sheets(): array\n            {\n                return [\n                    'Some Random Sheet Name' => new class implements SkipsUnknownSheets\n                    {\n                        /**\n                         * @param  string|int  $sheetName\n                         */\n                        public function onUnknownSheet($sheetName)\n                        {\n                            Assert::assertEquals('Some Random Sheet Name', $sheetName);\n                        }\n                    },\n                ];\n            }\n        };\n\n        $import->import('import-multiple-sheets.xlsx');\n    }\n\n    public function test_unknown_sheet_indices_can_be_ignored()\n    {\n        $import = new class implements WithMultipleSheets, SkipsUnknownSheets\n        {\n            use Importable;\n\n            public $unknown;\n\n            public function sheets(): array\n            {\n                return [\n                    99999 => new class {\n                    },\n                ];\n            }\n\n            /**\n             * @param  string|int  $sheetName\n             */\n            public function onUnknownSheet($sheetName)\n            {\n                $this->unknown = $sheetName;\n            }\n        };\n\n        $import->import('import-multiple-sheets.xlsx');\n\n        $this->assertEquals(99999, $import->unknown);\n    }\n\n    public function test_unknown_sheet_indices_can_be_ignored_per_sheet()\n    {\n        $import = new class implements WithMultipleSheets\n        {\n            use Importable;\n\n            public function sheets(): array\n            {\n                return [\n                    99999 => new class implements SkipsUnknownSheets\n                    {\n                        /**\n                         * @param  string|int  $sheetName\n                         */\n                        public function onUnknownSheet($sheetName)\n                        {\n                            Assert::assertEquals(99999, $sheetName);\n                        }\n                    },\n                ];\n            }\n        };\n\n        $import->import('import-multiple-sheets.xlsx');\n    }\n\n    public function test_can_import_multiple_sheets()\n    {\n        $import = new class implements WithMultipleSheets\n        {\n            use Importable;\n\n            public function sheets(): array\n            {\n                return [\n                    new class implements ToArray\n                    {\n                        public function array(array $array)\n                        {\n                            Assert::assertEquals([\n                                ['1.A1', '1.B1'],\n                                ['1.A2', '1.B2'],\n                            ], $array);\n                        }\n                    },\n                    new class implements ToArray\n                    {\n                        public function array(array $array)\n                        {\n                            Assert::assertEquals([\n                                ['2.A1', '2.B1'],\n                                ['2.A2', '2.B2'],\n                            ], $array);\n                        }\n                    },\n                ];\n            }\n        };\n\n        $import->import('import-multiple-sheets.xlsx');\n    }\n\n    public function test_can_import_multiple_sheets_by_sheet_name()\n    {\n        $import = new class implements WithMultipleSheets\n        {\n            use Importable;\n\n            public function sheets(): array\n            {\n                return [\n                    'Sheet2' => new class implements ToArray\n                    {\n                        public function array(array $array)\n                        {\n                            Assert::assertEquals([\n                                ['2.A1', '2.B1'],\n                                ['2.A2', '2.B2'],\n                            ], $array);\n                        }\n                    },\n                    'Sheet1' => new class implements ToArray\n                    {\n                        public function array(array $array)\n                        {\n                            Assert::assertEquals([\n                                ['1.A1', '1.B1'],\n                                ['1.A2', '1.B2'],\n                            ], $array);\n                        }\n                    },\n                ];\n            }\n        };\n\n        $import->import('import-multiple-sheets.xlsx');\n    }\n\n    public function test_can_import_multiple_sheets_by_sheet_index_and_name()\n    {\n        $import = new class implements WithMultipleSheets\n        {\n            use Importable;\n\n            public $sheets = [];\n\n            public function __construct()\n            {\n                $this->sheets = [\n                    0        => new class implements ToArray\n                    {\n                        public $called = false;\n\n                        public function array(array $array)\n                        {\n                            $this->called = true;\n                            Assert::assertEquals([\n                                ['1.A1', '1.B1'],\n                                ['1.A2', '1.B2'],\n                            ], $array);\n                        }\n                    },\n                    'Sheet2' => new class implements ToArray\n                    {\n                        public $called = false;\n\n                        public function array(array $array)\n                        {\n                            $this->called = true;\n                            Assert::assertEquals([\n                                ['2.A1', '2.B1'],\n                                ['2.A2', '2.B2'],\n                            ], $array);\n                        }\n                    },\n                ];\n            }\n\n            public function sheets(): array\n            {\n                return $this->sheets;\n            }\n        };\n\n        $import->import('import-multiple-sheets.xlsx');\n\n        foreach ($import->sheets as $sheet) {\n            $this->assertTrue($sheet->called);\n        }\n    }\n\n    public function test_can_import_multiple_sheets_by_sheet_name_and_index()\n    {\n        $import = new class implements WithMultipleSheets\n        {\n            use Importable;\n\n            public $sheets = [];\n\n            public function __construct()\n            {\n                $this->sheets = [\n                    'Sheet1' => new class implements ToArray\n                    {\n                        public $called = false;\n\n                        public function array(array $array)\n                        {\n                            $this->called = true;\n                            Assert::assertEquals([\n                                ['1.A1', '1.B1'],\n                                ['1.A2', '1.B2'],\n                            ], $array);\n                        }\n                    },\n                    1        => new class implements ToArray\n                    {\n                        public $called = false;\n\n                        public function array(array $array)\n                        {\n                            $this->called = true;\n                            Assert::assertEquals([\n                                ['2.A1', '2.B1'],\n                                ['2.A2', '2.B2'],\n                            ], $array);\n                        }\n                    },\n                ];\n            }\n\n            public function sheets(): array\n            {\n                return $this->sheets;\n            }\n        };\n\n        $import->import('import-multiple-sheets.xlsx');\n\n        foreach ($import->sheets as $sheet) {\n            $this->assertTrue($sheet->called);\n        }\n    }\n}\n"
  },
  {
    "path": "tests/Concerns/WithPropertiesTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Concerns;\n\nuse Maatwebsite\\Excel\\Concerns\\Exportable;\nuse Maatwebsite\\Excel\\Concerns\\WithProperties;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\n\nclass WithPropertiesTest extends TestCase\n{\n    public function test_can_set_custom_document_properties()\n    {\n        $export = new class implements WithProperties\n        {\n            use Exportable;\n\n            public function properties(): array\n            {\n                return [\n                    'creator'        => 'A',\n                    'lastModifiedBy' => 'B',\n                    'title'          => 'C',\n                    'description'    => 'D',\n                    'subject'        => 'E',\n                    'keywords'       => 'F',\n                    'category'       => 'G',\n                    'manager'        => 'H',\n                    'company'        => 'I',\n                ];\n            }\n        };\n\n        $export->store('with-properties.xlsx');\n\n        $spreadsheet = $this->read(__DIR__ . '/../Data/Disks/Local/with-properties.xlsx', 'Xlsx');\n        $props       = $spreadsheet->getProperties();\n\n        $this->assertEquals('A', $props->getCreator());\n        $this->assertEquals('B', $props->getLastModifiedBy());\n        $this->assertEquals('C', $props->getTitle());\n        $this->assertEquals('D', $props->getDescription());\n        $this->assertEquals('E', $props->getSubject());\n        $this->assertEquals('F', $props->getKeywords());\n        $this->assertEquals('G', $props->getCategory());\n        $this->assertEquals('H', $props->getManager());\n        $this->assertEquals('I', $props->getCompany());\n    }\n\n    public function test_it_merges_with_default_properties()\n    {\n        config()->set('excel.exports.properties.title', 'Default Title');\n        config()->set('excel.exports.properties.description', 'Default Description');\n\n        $export = new class implements WithProperties\n        {\n            use Exportable;\n\n            public function properties(): array\n            {\n                return [\n                    'description' => 'Custom Description',\n                ];\n            }\n        };\n\n        $export->store('with-properties.xlsx');\n\n        $spreadsheet = $this->read(__DIR__ . '/../Data/Disks/Local/with-properties.xlsx', 'Xlsx');\n        $props       = $spreadsheet->getProperties();\n\n        $this->assertEquals('Default Title', $props->getTitle());\n        $this->assertEquals('Custom Description', $props->getDescription());\n    }\n\n    public function test_it_ignores_empty_properties()\n    {\n        $export = new class implements WithProperties\n        {\n            use Exportable;\n\n            public function properties(): array\n            {\n                return [\n                    'description' => '',\n                ];\n            }\n        };\n\n        $export->store('with-properties.xlsx');\n\n        $spreadsheet = $this->read(__DIR__ . '/../Data/Disks/Local/with-properties.xlsx', 'Xlsx');\n        $props       = $spreadsheet->getProperties();\n\n        $this->assertSame('Unknown Creator', $props->getCreator());\n        $this->assertSame('Untitled Spreadsheet', $props->getTitle());\n        $this->assertSame('', $props->getDescription());\n    }\n}\n"
  },
  {
    "path": "tests/Concerns/WithReadFilterTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Concerns;\n\nuse Maatwebsite\\Excel\\Concerns\\Importable;\nuse Maatwebsite\\Excel\\Concerns\\WithReadFilter;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\nuse PhpOffice\\PhpSpreadsheet\\Reader\\IReadFilter;\nuse PHPUnit\\Framework\\Assert;\n\nclass WithReadFilterTest extends TestCase\n{\n    public function test_can_register_custom_read_filter()\n    {\n        $export = new class implements WithReadFilter\n        {\n            use Importable;\n\n            public function readFilter(): IReadFilter\n            {\n                return new class implements IReadFilter\n                {\n                    public function readCell($column, $row, $worksheetName = '')\n                    {\n                        // Assert read filter is being called.\n                        // If assertion is not called, test will fail due to\n                        // test having no other assertions.\n                        Assert::assertTrue(true);\n\n                        return true;\n                    }\n                };\n            }\n        };\n\n        $export->toArray('import-users.xlsx');\n    }\n}\n"
  },
  {
    "path": "tests/Concerns/WithSkipDuplicatesTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Concerns;\n\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Support\\Facades\\DB;\nuse Maatwebsite\\Excel\\Concerns\\Importable;\nuse Maatwebsite\\Excel\\Concerns\\ToModel;\nuse Maatwebsite\\Excel\\Concerns\\WithBatchInserts;\nuse Maatwebsite\\Excel\\Concerns\\WithSkipDuplicates;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database\\User;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\n\nclass WithSkipDuplicatesTest extends TestCase\n{\n    /**\n     * Setup the test environment.\n     */\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $this->loadLaravelMigrations(['--database' => 'testing']);\n    }\n\n    public function test_can_skip_duplicate_models_in_batches()\n    {\n        User::create([\n            'name'      => 'Funny Banana',\n            'email'     => 'patrick@maatwebsite.nl',\n            'password'  => 'password',\n        ]);\n\n        DB::connection()->enableQueryLog();\n\n        $import = new class implements ToModel, WithBatchInserts, WithSkipDuplicates\n        {\n            use Importable;\n\n            /**\n             * @param  array  $row\n             * @return Model|null\n             */\n            public function model(array $row)\n            {\n                return new User([\n                    'name'     => $row[0],\n                    'email'    => $row[1],\n                    'password' => 'secret',\n                ]);\n            }\n\n            /**\n             * @return string|array\n             */\n            public function uniqueBy()\n            {\n                return 'email';\n            }\n\n            /**\n             * @return int\n             */\n            public function batchSize(): int\n            {\n                return 2;\n            }\n        };\n\n        $import->import('import-users.xlsx');\n\n        $this->assertCount(1, DB::getQueryLog());\n        DB::connection()->disableQueryLog();\n\n        $this->assertDatabaseHas('users', [\n            'name'      => 'Funny Banana',\n            'email'     => 'patrick@maatwebsite.nl',\n            'password'  => 'password',\n        ]);\n\n        $this->assertDatabaseHas('users', [\n            'name'      => 'Taylor Otwell',\n            'email'     => 'taylor@laravel.com',\n            'password'  => 'secret',\n        ]);\n\n        $this->assertEquals(2, User::count());\n    }\n\n    public function test_can_skip_duplicate_models_in_rows()\n    {\n        User::create([\n            'name'      => 'Funny Potato',\n            'email'     => 'patrick@maatwebsite.nl',\n            'password'  => 'password',\n        ]);\n\n        DB::connection()->enableQueryLog();\n\n        $import = new class implements ToModel, WithSkipDuplicates\n        {\n            use Importable;\n\n            /**\n             * @param  array  $row\n             * @return Model|Model[]|null\n             */\n            public function model(array $row)\n            {\n                return new User([\n                    'name'     => $row[0],\n                    'email'    => $row[1],\n                    'password' => 'secret',\n                ]);\n            }\n\n            /**\n             * @return string|array\n             */\n            public function uniqueBy()\n            {\n                return 'email';\n            }\n        };\n\n        $import->import('import-users.xlsx');\n\n        $this->assertCount(2, DB::getQueryLog());\n        DB::connection()->disableQueryLog();\n\n        $this->assertDatabaseHas('users', [\n            'name'      => 'Funny Potato',\n            'email'     => 'patrick@maatwebsite.nl',\n            'password'  => 'password',\n        ]);\n\n        $this->assertDatabaseHas('users', [\n            'name'      => 'Taylor Otwell',\n            'email'     => 'taylor@laravel.com',\n            'password'  => 'secret',\n        ]);\n\n        $this->assertEquals(2, User::count());\n    }\n}\n"
  },
  {
    "path": "tests/Concerns/WithStartRowTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Concerns;\n\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Maatwebsite\\Excel\\Concerns\\Importable;\nuse Maatwebsite\\Excel\\Concerns\\ToArray;\nuse Maatwebsite\\Excel\\Concerns\\ToModel;\nuse Maatwebsite\\Excel\\Concerns\\WithStartRow;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database\\User;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\nuse PHPUnit\\Framework\\Assert;\n\nclass WithStartRowTest extends TestCase\n{\n    /**\n     * Setup the test environment.\n     */\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $this->loadLaravelMigrations(['--database' => 'testing']);\n    }\n\n    public function test_can_import_each_row_to_model_with_different_start_row()\n    {\n        $import = new class implements ToModel, WithStartRow\n        {\n            use Importable;\n\n            /**\n             * @param  array  $row\n             * @return Model\n             */\n            public function model(array $row): Model\n            {\n                return new User([\n                    'name'     => $row[0],\n                    'email'    => $row[1],\n                    'password' => 'secret',\n                ]);\n            }\n\n            /**\n             * @return int\n             */\n            public function startRow(): int\n            {\n                return 5;\n            }\n        };\n\n        $import->import('import-users-with-different-heading-row.xlsx');\n\n        $this->assertDatabaseHas('users', [\n            'name'  => 'Patrick Brouwers',\n            'email' => 'patrick@maatwebsite.nl',\n        ]);\n\n        $this->assertDatabaseHas('users', [\n            'name'  => 'Taylor Otwell',\n            'email' => 'taylor@laravel.com',\n        ]);\n    }\n\n    public function test_can_import_to_array_with_start_row()\n    {\n        $import = new class implements ToArray, WithStartRow\n        {\n            use Importable;\n\n            /**\n             * @param  array  $array\n             */\n            public function array(array $array)\n            {\n                Assert::assertEquals([\n                    [\n                        'Patrick Brouwers',\n                        'patrick@maatwebsite.nl',\n                    ],\n                    [\n                        'Taylor Otwell',\n                        'taylor@laravel.com',\n                    ],\n                ], $array);\n            }\n\n            /**\n             * @return int\n             */\n            public function startRow(): int\n            {\n                return 5;\n            }\n        };\n\n        $import->import('import-users-with-different-heading-row.xlsx');\n    }\n}\n"
  },
  {
    "path": "tests/Concerns/WithStrictNullComparisonTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Concerns;\n\nuse Illuminate\\Support\\Collection;\nuse Maatwebsite\\Excel\\Concerns\\Exportable;\nuse Maatwebsite\\Excel\\Concerns\\FromCollection;\nuse Maatwebsite\\Excel\\Concerns\\WithHeadings;\nuse Maatwebsite\\Excel\\Concerns\\WithStrictNullComparison;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\n\nclass WithStrictNullComparisonTest extends TestCase\n{\n    public function test_exported_zero_values_are_not_null_when_exporting_with_strict_null_comparison()\n    {\n        $export = new class implements FromCollection, WithHeadings, WithStrictNullComparison\n        {\n            use Exportable;\n\n            /**\n             * @return Collection\n             */\n            public function collection()\n            {\n                return collect([\n                    ['string', '0', 0, 0.0, 'string'],\n                ]);\n            }\n\n            /**\n             * @return array\n             */\n            public function headings(): array\n            {\n                return ['string', '0', 0, 0.0, 'string'];\n            }\n        };\n\n        $response = $export->store('with-strict-null-comparison-store.xlsx');\n\n        $this->assertTrue($response);\n\n        $actual = $this->readAsArray(__DIR__ . '/../Data/Disks/Local/with-strict-null-comparison-store.xlsx', 'Xlsx');\n\n        $expected = [\n            ['string', 0.0, 0.0, 0.0, 'string'],\n            ['string', 0.0, 0.0, 0.0, 'string'],\n        ];\n\n        $this->assertEquals($expected, $actual);\n    }\n\n    public function test_exported_zero_values_are_null_when_not_exporting_with_strict_null_comparison()\n    {\n        $export = new class implements FromCollection, WithHeadings\n        {\n            use Exportable;\n\n            /**\n             * @return Collection\n             */\n            public function collection()\n            {\n                return collect([\n                    ['string', 0, 0.0, 'string'],\n                ]);\n            }\n\n            /**\n             * @return array\n             */\n            public function headings(): array\n            {\n                return ['string', 0, 0.0, 'string'];\n            }\n        };\n\n        $response = $export->store('without-strict-null-comparison-store.xlsx');\n\n        $this->assertTrue($response);\n\n        $actual = $this->readAsArray(__DIR__ . '/../Data/Disks/Local/without-strict-null-comparison-store.xlsx', 'Xlsx');\n\n        $expected = [\n            ['string', null, null, 'string'],\n            ['string', null, null, 'string'],\n        ];\n\n        $this->assertEquals($expected, $actual);\n    }\n\n    public function test_exports_trailing_empty_cells()\n    {\n        $export = new class implements FromCollection, WithStrictNullComparison\n        {\n            use Exportable;\n\n            /**\n             * @return Collection\n             */\n            public function collection()\n            {\n                return collect([\n                    ['a1', '', '', 'd1', ''],\n                    ['a2', '', '', 'd2', ''],\n                ]);\n            }\n        };\n\n        $response = $export->store('empty-cells.csv');\n\n        $this->assertTrue($response);\n\n        $file   = __DIR__ . '/../Data/Disks/Local/empty-cells.csv';\n        $actual = $this->readAsArray($file, 'Csv');\n\n        $expected = [\n            ['a1', null, null, 'd1'],\n            ['a2', null, null, 'd2'],\n        ];\n\n        $this->assertEquals($expected, $actual);\n\n        $contents = file_get_contents($file);\n        $this->assertStringContains('\"a1\",\"\",\"\",\"d1\",\"\"', $contents);\n        $this->assertStringContains('\"a2\",\"\",\"\",\"d2\",\"\"', $contents);\n    }\n\n    public function test_exports_trailing_empty_cells_by_setting_config_strict_null_comparison()\n    {\n        config()->set('excel.exports.strict_null_comparison', false);\n\n        $export = new class implements FromCollection\n        {\n            use Exportable;\n\n            /**\n             * @return Collection\n             */\n            public function collection()\n            {\n                return collect([\n                    ['a1', '', '', 'd1', ''],\n                    ['a2', '', '', 'd2', ''],\n                ]);\n            }\n        };\n\n        $file = __DIR__ . '/../Data/Disks/Local/empty-cells-config.csv';\n\n        $export->store('empty-cells-config.csv');\n\n        $contents = file_get_contents($file);\n        $this->assertStringContains('\"a1\",\"\",\"\",\"d1\"', $contents);\n\n        config()->set('excel.exports.strict_null_comparison', true);\n\n        $export->store('empty-cells-config.csv');\n\n        $contents = file_get_contents($file);\n        $this->assertStringContains('\"a1\",\"\",\"\",\"d1\",\"\"', $contents);\n    }\n}\n"
  },
  {
    "path": "tests/Concerns/WithStylesTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Concerns;\n\nuse Maatwebsite\\Excel\\Concerns\\Exportable;\nuse Maatwebsite\\Excel\\Concerns\\FromArray;\nuse Maatwebsite\\Excel\\Concerns\\WithStyles;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\nuse PhpOffice\\PhpSpreadsheet\\Worksheet\\Worksheet;\n\nclass WithStylesTest extends TestCase\n{\n    public function test_can_configure_styles()\n    {\n        $export = new class implements FromArray, WithStyles\n        {\n            use Exportable;\n\n            public function styles(Worksheet $sheet)\n            {\n                return [\n                    1    => ['font' => ['italic' => true]],\n                    'B2' => ['font' => ['bold' => true]],\n                    'C'  => ['font' => ['size' => 16]],\n                ];\n            }\n\n            public function array(): array\n            {\n                return [\n                    ['A1', 'B1', 'C1'],\n                    ['A2', 'B2', 'C2'],\n                ];\n            }\n        };\n\n        $export->store('with-styles.xlsx');\n\n        $spreadsheet = $this->read(__DIR__ . '/../Data/Disks/Local/with-styles.xlsx', 'Xlsx');\n        $sheet       = $spreadsheet->getActiveSheet();\n\n        $this->assertTrue($sheet->getStyle('A1')->getFont()->getItalic());\n        $this->assertTrue($sheet->getStyle('B1')->getFont()->getItalic());\n        $this->assertTrue($sheet->getStyle('B2')->getFont()->getBold());\n        $this->assertFalse($sheet->getStyle('A2')->getFont()->getBold());\n        $this->assertEquals(16, $sheet->getStyle('C2')->getFont()->getSize());\n    }\n}\n"
  },
  {
    "path": "tests/Concerns/WithTitleTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Concerns;\n\nuse Maatwebsite\\Excel\\Concerns\\Exportable;\nuse Maatwebsite\\Excel\\Concerns\\WithMultipleSheets;\nuse Maatwebsite\\Excel\\Concerns\\WithTitle;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\WithTitleExport;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\n\nclass WithTitleTest extends TestCase\n{\n    public function test_can_export_with_title()\n    {\n        $export = new WithTitleExport();\n\n        $response = $export->store('with-title-store.xlsx');\n\n        $this->assertTrue($response);\n\n        $spreadsheet = $this->read(__DIR__ . '/../Data/Disks/Local/with-title-store.xlsx', 'Xlsx');\n\n        $this->assertEquals('given-title', $spreadsheet->getProperties()->getTitle());\n        $this->assertEquals('given-title', $spreadsheet->getActiveSheet()->getTitle());\n    }\n\n    public function test_can_export_sheet_title_when_longer_than_max_length()\n    {\n        $export = new class implements WithTitle, WithMultipleSheets\n        {\n            use Exportable;\n\n            /**\n             * @return string\n             */\n            public function title(): string\n            {\n                return '12/3456789123/45678912345/678912345/6789';\n            }\n\n            public function sheets(): array\n            {\n                return [$this];\n            }\n        };\n\n        $response = $export->store('with-title-store.xlsx');\n        $this->assertTrue($response);\n\n        $spreadsheet = $this->read(__DIR__ . '/../Data/Disks/Local/with-title-store.xlsx', 'Xlsx');\n\n        $this->assertEquals('12/3456789123/45678912345/678912345/6789', $spreadsheet->getProperties()->getTitle());\n        $this->assertEquals('1234567891234567891234567891234', $spreadsheet->getActiveSheet()->getTitle());\n    }\n}\n"
  },
  {
    "path": "tests/Concerns/WithUpsertsTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Concerns;\n\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Support\\Facades\\DB;\nuse Maatwebsite\\Excel\\Concerns\\Importable;\nuse Maatwebsite\\Excel\\Concerns\\ToModel;\nuse Maatwebsite\\Excel\\Concerns\\WithBatchInserts;\nuse Maatwebsite\\Excel\\Concerns\\WithUpsertColumns;\nuse Maatwebsite\\Excel\\Concerns\\WithUpserts;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database\\User;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\n\nclass WithUpsertsTest extends TestCase\n{\n    /**\n     * Setup the test environment.\n     */\n    protected function setUp(): void\n    {\n        if (!method_exists(Builder::class, 'upsert')) {\n            $this->markTestSkipped('The upsert feature is available on Laravel 8.10+');\n        }\n\n        parent::setUp();\n\n        $this->loadLaravelMigrations(['--database' => 'testing']);\n    }\n\n    public function test_can_upsert_models_in_batches()\n    {\n        User::create([\n            'name'      => 'Funny Banana',\n            'email'     => 'patrick@maatwebsite.nl',\n            'password'  => 'password',\n        ]);\n\n        DB::connection()->enableQueryLog();\n\n        $import = new class implements ToModel, WithBatchInserts, WithUpserts\n        {\n            use Importable;\n\n            /**\n             * @param  array  $row\n             * @return Model|null\n             */\n            public function model(array $row)\n            {\n                return new User([\n                    'name'     => $row[0],\n                    'email'    => $row[1],\n                    'password' => 'secret',\n                ]);\n            }\n\n            /**\n             * @return string|array\n             */\n            public function uniqueBy()\n            {\n                return 'email';\n            }\n\n            /**\n             * @return int\n             */\n            public function batchSize(): int\n            {\n                return 2;\n            }\n        };\n\n        $import->import('import-users.xlsx');\n\n        $this->assertCount(1, DB::getQueryLog());\n        DB::connection()->disableQueryLog();\n\n        $this->assertDatabaseHas('users', [\n            'name'      => 'Patrick Brouwers',\n            'email'     => 'patrick@maatwebsite.nl',\n            'password'  => 'secret',\n        ]);\n\n        $this->assertDatabaseHas('users', [\n            'name'      => 'Taylor Otwell',\n            'email'     => 'taylor@laravel.com',\n            'password'  => 'secret',\n        ]);\n\n        $this->assertEquals(2, User::count());\n    }\n\n    public function test_can_upsert_models_in_rows()\n    {\n        User::create([\n            'name'      => 'Funny Potato',\n            'email'     => 'patrick@maatwebsite.nl',\n            'password'  => 'password',\n        ]);\n\n        DB::connection()->enableQueryLog();\n\n        $import = new class implements ToModel, WithUpserts\n        {\n            use Importable;\n\n            /**\n             * @param  array  $row\n             * @return Model|Model[]|null\n             */\n            public function model(array $row)\n            {\n                return new User([\n                    'name'     => $row[0],\n                    'email'    => $row[1],\n                    'password' => 'secret',\n                ]);\n            }\n\n            /**\n             * @return string|array\n             */\n            public function uniqueBy()\n            {\n                return 'email';\n            }\n        };\n\n        $import->import('import-users.xlsx');\n\n        $this->assertCount(2, DB::getQueryLog());\n        DB::connection()->disableQueryLog();\n\n        $this->assertDatabaseHas('users', [\n            'name'      => 'Patrick Brouwers',\n            'email'     => 'patrick@maatwebsite.nl',\n            'password'  => 'secret',\n        ]);\n\n        $this->assertDatabaseHas('users', [\n            'name'      => 'Taylor Otwell',\n            'email'     => 'taylor@laravel.com',\n            'password'  => 'secret',\n        ]);\n\n        $this->assertEquals(2, User::count());\n    }\n\n    public function test_can_upsert_models_in_batches_with_defined_upsert_columns()\n    {\n        User::create([\n            'name'      => 'Funny Banana',\n            'email'     => 'patrick@maatwebsite.nl',\n            'password'  => 'password',\n        ]);\n\n        DB::connection()->enableQueryLog();\n\n        $import = new class implements ToModel, WithBatchInserts, WithUpserts, WithUpsertColumns\n        {\n            use Importable;\n\n            /**\n             * @param  array  $row\n             * @return Model|null\n             */\n            public function model(array $row)\n            {\n                return new User([\n                    'name'     => $row[0],\n                    'email'    => $row[1],\n                    'password' => 'secret',\n                ]);\n            }\n\n            /**\n             * @return string|array\n             */\n            public function uniqueBy()\n            {\n                return 'email';\n            }\n\n            /**\n             * @return array\n             */\n            public function upsertColumns()\n            {\n                return ['name'];\n            }\n\n            /**\n             * @return int\n             */\n            public function batchSize(): int\n            {\n                return 2;\n            }\n        };\n\n        $import->import('import-users.xlsx');\n\n        $this->assertCount(1, DB::getQueryLog());\n        DB::connection()->disableQueryLog();\n\n        $this->assertDatabaseHas('users', [\n            'name'      => 'Patrick Brouwers',\n            'email'     => 'patrick@maatwebsite.nl',\n            'password'  => 'password',\n        ]);\n\n        $this->assertDatabaseHas('users', [\n            'name'      => 'Taylor Otwell',\n            'email'     => 'taylor@laravel.com',\n            'password'  => 'secret',\n        ]);\n\n        $this->assertEquals(2, User::count());\n    }\n\n    public function test_can_upsert_models_in_rows_with_defined_upsert_columns()\n    {\n        User::create([\n            'name'      => 'Funny Potato',\n            'email'     => 'patrick@maatwebsite.nl',\n            'password'  => 'password',\n        ]);\n\n        DB::connection()->enableQueryLog();\n\n        $import = new class implements ToModel, WithUpserts, WithUpsertColumns\n        {\n            use Importable;\n\n            /**\n             * @param  array  $row\n             * @return Model|Model[]|null\n             */\n            public function model(array $row)\n            {\n                return new User([\n                    'name'     => $row[0],\n                    'email'    => $row[1],\n                    'password' => 'secret',\n                ]);\n            }\n\n            /**\n             * @return string|array\n             */\n            public function uniqueBy()\n            {\n                return 'email';\n            }\n\n            /**\n             * @return array\n             */\n            public function upsertColumns()\n            {\n                return ['name'];\n            }\n        };\n\n        $import->import('import-users.xlsx');\n\n        $this->assertCount(2, DB::getQueryLog());\n        DB::connection()->disableQueryLog();\n\n        $this->assertDatabaseHas('users', [\n            'name'      => 'Patrick Brouwers',\n            'email'     => 'patrick@maatwebsite.nl',\n            'password'  => 'password',\n        ]);\n\n        $this->assertDatabaseHas('users', [\n            'name'      => 'Taylor Otwell',\n            'email'     => 'taylor@laravel.com',\n            'password'  => 'secret',\n        ]);\n\n        $this->assertEquals(2, User::count());\n    }\n}\n"
  },
  {
    "path": "tests/Concerns/WithValidationTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Concerns;\n\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Support\\Collection;\nuse Illuminate\\Validation\\Rule;\nuse Maatwebsite\\Excel\\Concerns\\Importable;\nuse Maatwebsite\\Excel\\Concerns\\OnEachRow;\nuse Maatwebsite\\Excel\\Concerns\\SkipsEmptyRows;\nuse Maatwebsite\\Excel\\Concerns\\ToArray;\nuse Maatwebsite\\Excel\\Concerns\\ToCollection;\nuse Maatwebsite\\Excel\\Concerns\\ToModel;\nuse Maatwebsite\\Excel\\Concerns\\WithBatchInserts;\nuse Maatwebsite\\Excel\\Concerns\\WithGroupedHeadingRow;\nuse Maatwebsite\\Excel\\Concerns\\WithHeadingRow;\nuse Maatwebsite\\Excel\\Concerns\\WithValidation;\nuse Maatwebsite\\Excel\\Row;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database\\User;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\nuse Maatwebsite\\Excel\\Validators\\ValidationException;\nuse PHPUnit\\Framework\\Assert;\n\nclass WithValidationTest extends TestCase\n{\n    /**\n     * Setup the test environment.\n     */\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $this->loadLaravelMigrations(['--database' => 'testing']);\n        $this->loadMigrationsFrom(dirname(__DIR__) . '/Data/Stubs/Database/Migrations');\n    }\n\n    public function test_can_validate_rows()\n    {\n        $import = new class implements ToModel, WithValidation\n        {\n            use Importable;\n\n            /**\n             * @param  array  $row\n             * @return Model|null\n             */\n            public function model(array $row)\n            {\n                return new User([\n                    'name'     => $row[0],\n                    'email'    => $row[1],\n                    'password' => 'secret',\n                ]);\n            }\n\n            /**\n             * @return array\n             */\n            public function rules(): array\n            {\n                return [\n                    '1' => Rule::in(['patrick@maatwebsite.nl']),\n                ];\n            }\n        };\n\n        try {\n            $import->import('import-users.xlsx');\n        } catch (ValidationException $e) {\n            $this->validateFailure($e, 2, '1', [\n                'The selected 1(field)? is invalid.',\n            ]);\n\n            $this->assertRegex(\n                '/There was an error on row 2. The selected 1 (field)?is invalid./',\n                $e->errors()[0][0]\n            );\n        }\n\n        $this->assertInstanceOf(ValidationException::class, $e ?? null);\n    }\n\n    public function test_can_validate_rows_with_closure_validation_rules()\n    {\n        $import = new class implements ToModel, WithValidation\n        {\n            use Importable;\n\n            /**\n             * @param  array  $row\n             * @return Model|null\n             */\n            public function model(array $row)\n            {\n                return new User([\n                    'name'     => $row[0],\n                    'email'    => $row[1],\n                    'password' => 'secret',\n                ]);\n            }\n\n            /**\n             * @return array\n             */\n            public function rules(): array\n            {\n                return [\n                    '1' => function ($attribute, $value, $onFail) {\n                        if ($value !== 'patrick@maatwebsite.nl') {\n                            $onFail(sprintf('Value in column 1 is not an allowed e-mail.'));\n                        }\n                    },\n                ];\n            }\n        };\n\n        try {\n            $import->import('import-users.xlsx');\n        } catch (ValidationException $e) {\n            $this->validateFailure($e, 2, '1', [\n                'Value in column 1 is not an allowed e-mail.',\n            ]);\n\n            $this->assertRegex(\n                '/There was an error on row 2. Value in column 1 is not an allowed e-mail./',\n                $e->errors()[0][0]\n            );\n        }\n\n        $this->assertInstanceOf(ValidationException::class, $e ?? null);\n    }\n\n    public function test_can_validate_rows_with_custom_validation_rule_objects()\n    {\n        $import = new class implements ToModel, WithValidation\n        {\n            use Importable;\n\n            /**\n             * @param  array  $row\n             * @return Model|null\n             */\n            public function model(array $row)\n            {\n                return new User([\n                    'name'     => $row[0],\n                    'email'    => $row[1],\n                    'password' => 'secret',\n                ]);\n            }\n\n            /**\n             * @return array\n             */\n            public function rules(): array\n            {\n                return [\n                    '1' => new class implements \\Illuminate\\Contracts\\Validation\\Rule\n                    {\n                        /**\n                         * @param  string  $attribute\n                         * @param  mixed  $value\n                         * @return bool\n                         */\n                        public function passes($attribute, $value)\n                        {\n                            return $value === 'patrick@maatwebsite.nl';\n                        }\n\n                        /**\n                         * Get the validation error message.\n                         *\n                         * @return string|array\n                         */\n                        public function message()\n                        {\n                            return 'Value is not an allowed e-mail.';\n                        }\n                    },\n                ];\n            }\n        };\n\n        try {\n            $import->import('import-users.xlsx');\n        } catch (ValidationException $e) {\n            $this->validateFailure($e, 2, '1', [\n                'Value is not an allowed e-mail.',\n            ]);\n\n            $this->assertRegex(\n                '/There was an error on row 2. Value is not an allowed e-mail./',\n                $e->errors()[0][0]\n            );\n        }\n\n        $this->assertInstanceOf(ValidationException::class, $e ?? null);\n    }\n\n    public function test_can_validate_rows_with_conditionality()\n    {\n        $import = new class implements ToModel, WithValidation\n        {\n            use Importable;\n\n            /**\n             * @param  array  $row\n             * @return Model|null\n             */\n            public function model(array $row)\n            {\n                return new User([\n                    'name'     => $row[0],\n                    'email'    => $row[1],\n                    'password' => 'secret',\n                ]);\n            }\n\n            /**\n             * @return array\n             */\n            public function rules(): array\n            {\n                return [\n                    'conditional_required_column' => 'required_if:1,patrick@maatwebsite.nl',\n                ];\n            }\n        };\n\n        try {\n            $import->import('import-users.xlsx');\n        } catch (ValidationException $e) {\n            $this->validateFailure($e, 1, 'conditional_required_column', [\n                'The conditional_required_column field is required when 1.1 is patrick@maatwebsite.nl.',\n            ]);\n        }\n\n        $this->assertInstanceOf(ValidationException::class, $e ?? null);\n    }\n\n    public function test_can_validate_rows_with_unless_conditionality()\n    {\n        $import = new class implements ToModel, WithValidation\n        {\n            use Importable;\n\n            /**\n             * @param  array  $row\n             * @return Model|null\n             */\n            public function model(array $row)\n            {\n                return new User([\n                    'name'     => $row[0],\n                    'email'    => $row[1],\n                    'password' => 'secret',\n                ]);\n            }\n\n            /**\n             * @return array\n             */\n            public function rules(): array\n            {\n                return [\n                    'conditional_required_unless_column' => 'required_unless:1,patrick@maatwebsite.nl',\n                ];\n            }\n        };\n\n        try {\n            $import->import('import-users.xlsx');\n        } catch (ValidationException $e) {\n            $this->validateFailure($e, 2, 'conditional_required_unless_column', [\n                'The conditional_required_unless_column field is required unless 2.1 is in patrick@maatwebsite.nl.',\n            ]);\n        }\n\n        $this->assertInstanceOf(ValidationException::class, $e ?? null);\n    }\n\n    public function test_can_validate_rows_with_combined_rules_with_colons()\n    {\n        $import = new class implements ToModel, WithValidation\n        {\n            use Importable;\n\n            /**\n             * @param  array  $row\n             * @return Model|null\n             */\n            public function model(array $row)\n            {\n                return new User([\n                    'name'     => $row[0],\n                    'email'    => $row[1],\n                    'password' => 'secret',\n                ]);\n            }\n\n            /**\n             * @return array\n             */\n            public function rules(): array\n            {\n                return [\n                    '1' => 'required_with:0|unique:users,email',\n                ];\n            }\n        };\n\n        $import->import('import-users.xlsx');\n\n        $this->assertDatabaseHas('users', [\n            'email' => 'patrick@maatwebsite.nl',\n        ]);\n\n        try {\n            $import->import('import-users.xlsx');\n        } catch (ValidationException $e) {\n            $this->validateFailure($e, 1, '1', [\n                'The 1 has already been taken.',\n            ]);\n        }\n\n        $this->assertInstanceOf(ValidationException::class, $e ?? null);\n    }\n\n    public function test_can_validate_with_custom_attributes()\n    {\n        $import = new class implements ToModel, WithValidation\n        {\n            use Importable;\n\n            /**\n             * @param  array  $row\n             * @return Model|null\n             */\n            public function model(array $row)\n            {\n                return new User([\n                    'name'     => $row[0],\n                    'email'    => $row[1],\n                    'password' => 'secret',\n                ]);\n            }\n\n            /**\n             * @return array\n             */\n            public function rules(): array\n            {\n                return [\n                    '1' => Rule::in(['patrick@maatwebsite.nl']),\n                ];\n            }\n\n            /**\n             * @return array\n             */\n            public function customValidationAttributes()\n            {\n                return ['1' => 'email'];\n            }\n        };\n\n        try {\n            $import->import('import-users.xlsx');\n        } catch (ValidationException $e) {\n            $this->validateFailure($e, 2, 'email', [\n                'The selected email is invalid.',\n            ]);\n        }\n\n        $this->assertInstanceOf(ValidationException::class, $e ?? null);\n    }\n\n    public function test_can_validate_with_custom_attributes_pointing_to_another_attribute()\n    {\n        $import = new class implements ToModel, WithValidation\n        {\n            use Importable;\n\n            /**\n             * @param  array  $row\n             * @return Model|null\n             */\n            public function model(array $row)\n            {\n                return new User([\n                    'name'     => $row[0],\n                    'email'    => $row[1],\n                    'password' => 'secret',\n                ]);\n            }\n\n            /**\n             * @return array\n             */\n            public function rules(): array\n            {\n                return [\n                    '1' => ['required'],\n                    '2' => ['required_with:*.1'],\n                ];\n            }\n\n            /**\n             * @return array\n             */\n            public function customValidationAttributes()\n            {\n                return ['1' => 'email', '2' => 'password'];\n            }\n        };\n\n        try {\n            $import->import('import-users.xlsx');\n        } catch (ValidationException $e) {\n            $this->validateFailure($e, 1, 'password', [\n                'The password field is required when email is present.',\n            ]);\n        }\n\n        $this->assertInstanceOf(ValidationException::class, $e ?? null);\n    }\n\n    public function test_can_validate_with_custom_message()\n    {\n        $import = new class implements ToModel, WithValidation\n        {\n            use Importable;\n\n            /**\n             * @param  array  $row\n             * @return Model|null\n             */\n            public function model(array $row)\n            {\n                return new User([\n                    'name'     => $row[0],\n                    'email'    => $row[1],\n                    'password' => 'secret',\n                ]);\n            }\n\n            /**\n             * @return array\n             */\n            public function rules(): array\n            {\n                return [\n                    '1' => Rule::in(['patrick@maatwebsite.nl']),\n                ];\n            }\n\n            /**\n             * @return array\n             */\n            public function customValidationMessages()\n            {\n                return [\n                    '1.in' => 'Custom message for :attribute.',\n                ];\n            }\n        };\n\n        try {\n            $import->import('import-users.xlsx');\n        } catch (ValidationException $e) {\n            $this->validateFailure($e, 2, '1', [\n                'Custom message for 1.',\n            ]);\n        }\n\n        $this->assertInstanceOf(ValidationException::class, $e ?? null);\n    }\n\n    public function test_can_validate_rows_with_headings()\n    {\n        $import = new class implements ToModel, WithHeadingRow, WithValidation\n        {\n            use Importable;\n\n            /**\n             * @param  array  $row\n             * @return Model|null\n             */\n            public function model(array $row)\n            {\n                return new User([\n                    'name'     => $row['name'],\n                    'email'    => $row['email'],\n                    'password' => 'secret',\n                ]);\n            }\n\n            /**\n             * @return array\n             */\n            public function rules(): array\n            {\n                return [\n                    'email' => Rule::in(['patrick@maatwebsite.nl']),\n                ];\n            }\n        };\n\n        try {\n            $import->import('import-users-with-headings.xlsx');\n        } catch (ValidationException $e) {\n            $this->validateFailure($e, 3, 'email', [\n                'The selected email is invalid.',\n            ]);\n        }\n\n        $this->assertInstanceOf(ValidationException::class, $e ?? null);\n    }\n\n    public function test_can_validate_rows_with_grouped_headings()\n    {\n        $import = new class implements ToModel, WithGroupedHeadingRow, WithValidation\n        {\n            use Importable;\n\n            /**\n             * Prepare the data for validation.\n             *\n             * @param  array  $row\n             * @param  int  $index\n             * @return array\n             */\n            public function prepareForValidation(array $row, int $index)\n            {\n                if ($index === 2) {\n                    Assert::assertIsArray($row['options']);\n                    $row['options'] = 'not an array';\n                }\n\n                return $row;\n            }\n\n            /**\n             * @param  array  $row\n             * @return Model|null\n             */\n            public function model(array $row)\n            {\n                return new User([\n                    'name'     => $row['name'],\n                    'email'    => $row['email'],\n                    'password' => 'secret',\n                    'options'  => $row['options'],\n                ]);\n            }\n\n            /**\n             * @return array\n             */\n            public function rules(): array\n            {\n                return [\n                    'options' => 'array',\n                ];\n            }\n        };\n\n        try {\n            $import->import('import-users-with-grouped-headers.xlsx');\n        } catch (ValidationException $e) {\n            $this->validateFailure($e, 2, 'options', [\n                'The options( field)? must be an array.',\n            ]);\n        }\n\n        $this->assertInstanceOf(ValidationException::class, $e ?? null);\n    }\n\n    public function test_can_validate_rows_in_batches()\n    {\n        $import = new class implements ToModel, WithHeadingRow, WithBatchInserts, WithValidation\n        {\n            use Importable;\n\n            /**\n             * @param  array  $row\n             * @return Model|null\n             */\n            public function model(array $row)\n            {\n                return new User([\n                    'name'     => $row['name'],\n                    'email'    => $row['email'],\n                    'password' => 'secret',\n                ]);\n            }\n\n            /**\n             * @return int\n             */\n            public function batchSize(): int\n            {\n                return 2;\n            }\n\n            /**\n             * @return array\n             */\n            public function rules(): array\n            {\n                return [\n                    'email' => Rule::in(['patrick@maatwebsite.nl']),\n                ];\n            }\n        };\n\n        try {\n            $import->import('import-users-with-headings.xlsx');\n        } catch (ValidationException $e) {\n            $this->validateFailure($e, 3, 'email', [\n                'The selected email is invalid.',\n            ]);\n        }\n\n        $this->assertInstanceOf(ValidationException::class, $e ?? null);\n    }\n\n    public function test_can_validate_using_oneachrow()\n    {\n        $import = new class implements OnEachRow, WithHeadingRow, WithValidation\n        {\n            use Importable;\n\n            /**\n             * @param  Row  $row\n             * @return Model|null\n             */\n            public function onRow(Row $row)\n            {\n                $values = $row->toArray();\n\n                return new User([\n                    'name'     => $values['name'],\n                    'email'    => $values['email'],\n                    'password' => 'secret',\n                ]);\n            }\n\n            /**\n             * @return array\n             */\n            public function rules(): array\n            {\n                return [\n                    'email' => Rule::in(['patrick@maatwebsite.nl']),\n                ];\n            }\n        };\n\n        try {\n            $import->import('import-users-with-headings.xlsx');\n        } catch (ValidationException $e) {\n            $this->validateFailure($e, 3, 'email', [\n                'The selected email is invalid.',\n            ]);\n        }\n\n        $this->assertInstanceOf(ValidationException::class, $e ?? null);\n    }\n\n    public function test_can_validate_using_collection()\n    {\n        $import = new class implements ToCollection, WithHeadingRow, WithValidation\n        {\n            use Importable;\n\n            public function collection(Collection $rows)\n            {\n                //\n            }\n\n            /**\n             * @return array\n             */\n            public function rules(): array\n            {\n                return [\n                    'email' => Rule::in(['patrick@maatwebsite.nl']),\n                ];\n            }\n        };\n\n        try {\n            $import->import('import-users-with-headings.xlsx');\n        } catch (ValidationException $e) {\n            $this->validateFailure($e, 3, 'email', [\n                'The selected email is invalid.',\n            ]);\n        }\n\n        $this->assertInstanceOf(ValidationException::class, $e ?? null);\n    }\n\n    public function test_can_validate_using_array()\n    {\n        $import = new class implements ToArray, WithHeadingRow, WithValidation\n        {\n            use Importable;\n\n            public function array(array $rows)\n            {\n                //\n            }\n\n            /**\n             * @return array\n             */\n            public function rules(): array\n            {\n                return [\n                    'email' => Rule::in(['patrick@maatwebsite.nl']),\n                ];\n            }\n        };\n\n        try {\n            $import->import('import-users-with-headings.xlsx');\n        } catch (ValidationException $e) {\n            $this->validateFailure($e, 3, 'email', [\n                'The selected email is invalid.',\n            ]);\n        }\n\n        $this->assertInstanceOf(ValidationException::class, $e ?? null);\n    }\n\n    public function test_can_configure_validator()\n    {\n        $import = new class implements ToModel, WithValidation\n        {\n            use Importable;\n\n            /**\n             * @param  array  $row\n             * @return Model|null\n             */\n            public function model(array $row)\n            {\n                return new User([\n                    'name'     => $row[0],\n                    'email'    => $row[1],\n                    'password' => 'secret',\n                ]);\n            }\n\n            /**\n             * @return array\n             */\n            public function rules(): array\n            {\n                return [\n                    '1' => 'email',\n                ];\n            }\n\n            /**\n             * Configure the validator.\n             *\n             * @param  \\Illuminate\\Contracts\\Validation\\Validator  $validator\n             * @return void\n             */\n            public function withValidator($validator)\n            {\n                $validator->sometimes('*.1', Rule::in(['patrick@maatwebsite.nl']), function () {\n                    return true;\n                });\n            }\n        };\n\n        try {\n            $import->import('import-users.xlsx');\n        } catch (ValidationException $e) {\n            $this->validateFailure($e, 2, '1', [\n                'The selected 1 is invalid.',\n            ]);\n\n            $this->assertRegex(\n                '/There was an error on row 2. The selected 1 (field)?is invalid./',\n                $e->errors()[0][0]\n            );\n        }\n\n        $this->assertInstanceOf(ValidationException::class, $e ?? null);\n    }\n\n    public function test_can_prepare_using_toarray()\n    {\n        $import = new class implements ToArray, WithValidation\n        {\n            use Importable;\n\n            /**\n             * @return array\n             */\n            public function rules(): array\n            {\n                return [\n                    '1' => 'email',\n                ];\n            }\n\n            /**\n             * Prepare the data for validation.\n             *\n             * @param  array  $row\n             * @param  int  $index\n             * @return array\n             */\n            public function prepareForValidation(array $row, int $index)\n            {\n                if ($index === 2) {\n                    $row[1] = 'not an email';\n                }\n\n                return $row;\n            }\n\n            /**\n             * @param  array  $array\n             * @return array\n             */\n            public function array(array $array)\n            {\n                return [];\n            }\n        };\n\n        try {\n            $import->import('import-users.xlsx');\n        } catch (ValidationException $e) {\n            $this->validateFailure($e, 2, '1', [\n                'The 1( field)? must be a valid email address.',\n            ]);\n\n            $this->assertRegex(\n                '/There was an error on row 2. The 1( field)? must be a valid email address./',\n                $e->errors()[0][0]\n            );\n        }\n\n        $this->assertInstanceOf(ValidationException::class, $e ?? null);\n    }\n\n    public function test_can_prepare_using_tocollection()\n    {\n        $import = new class implements ToCollection, WithValidation\n        {\n            use Importable;\n\n            /**\n             * @return array\n             */\n            public function rules(): array\n            {\n                return [\n                    '1' => 'email',\n                ];\n            }\n\n            /**\n             * Prepare the data for validation.\n             *\n             * @param  array  $row\n             * @param  int  $index\n             * @return array\n             */\n            public function prepareForValidation(array $row, int $index)\n            {\n                if ($index === 2) {\n                    $row[1] = 'not an email';\n                }\n\n                return $row;\n            }\n\n            /**\n             * @param  \\Illuminate\\Support\\Collection  $collection\n             * @return mixed\n             */\n            public function collection(Collection $collection)\n            {\n                return collect();\n            }\n        };\n\n        try {\n            $import->import('import-users.xlsx');\n        } catch (ValidationException $e) {\n            $this->validateFailure($e, 2, '1', [\n                'The 1( field)? must be a valid email address.',\n            ]);\n\n            $this->assertRegex(\n                '/There was an error on row 2. The 1( field)? must be a valid email address./',\n                $e->errors()[0][0]\n            );\n        }\n\n        $this->assertInstanceOf(ValidationException::class, $e ?? null);\n    }\n\n    public function test_can_prepare_using_tomodel()\n    {\n        $import = new class implements ToModel, WithValidation\n        {\n            use Importable;\n\n            /**\n             * @return array\n             */\n            public function rules(): array\n            {\n                return [\n                    '1' => 'email',\n                ];\n            }\n\n            /**\n             * Prepare the data for validation.\n             *\n             * @param  array  $row\n             * @param  int  $index\n             * @return array\n             */\n            public function prepareForValidation(array $row, int $index)\n            {\n                if ($index === 2) {\n                    $row[1] = 'not an email';\n                }\n\n                return $row;\n            }\n\n            /**\n             * @param  array  $row\n             * @return \\Illuminate\\Database\\Eloquent\\Model|\\Illuminate\\Database\\Eloquent\\Model[]|null\n             */\n            public function model(array $row)\n            {\n                return new User([\n                    'name'     => $row[0],\n                    'email'    => $row[1],\n                    'password' => 'secret',\n                ]);\n            }\n        };\n\n        try {\n            $import->import('import-users.xlsx');\n        } catch (ValidationException $e) {\n            $this->validateFailure($e, 2, '1', [\n                'The 1( field)? must be a valid email address.',\n            ]);\n\n            $this->assertRegex(\n                '/There was an error on row 2. The 1( field)? must be a valid email address./',\n                $e->errors()[0][0]\n            );\n        }\n\n        $this->assertInstanceOf(ValidationException::class, $e ?? null);\n    }\n\n    public function test_can_prepare_using_oneachrow()\n    {\n        $import = new class implements OnEachRow, WithValidation\n        {\n            use Importable;\n\n            /**\n             * @return array\n             */\n            public function rules(): array\n            {\n                return [\n                    '1' => 'email',\n                ];\n            }\n\n            /**\n             * Prepare the data for validation.\n             *\n             * @param  array  $row\n             * @param  int  $index\n             * @return array\n             */\n            public function prepareForValidation(array $row, int $index)\n            {\n                if ($index === 2) {\n                    $row[1] = 'not an email';\n                }\n\n                return $row;\n            }\n\n            /**\n             * @param  \\Maatwebsite\\Excel\\Row  $row\n             * @return void\n             */\n            public function onRow(Row $row)\n            {\n                User::query()->create([\n                    'name'     => $row[0],\n                    'email'    => $row[1],\n                    'password' => 'secret',\n                ]);\n            }\n        };\n\n        try {\n            $import->import('import-users.xlsx');\n        } catch (ValidationException $e) {\n            $this->validateFailure($e, 2, '1', [\n                'The 1( field)? must be a valid email address.',\n            ]);\n\n            $this->assertRegex(\n                '/There was an error on row 2. The 1( field)? must be a valid email address./',\n                $e->errors()[0][0]\n            );\n        }\n\n        $this->assertInstanceOf(ValidationException::class, $e ?? null);\n    }\n\n    public function test_can_prepare_using_skipsemptyrows()\n    {\n        $import = new class implements OnEachRow, WithValidation, SkipsEmptyRows\n        {\n            use Importable;\n\n            /**\n             * @return array\n             */\n            public function rules(): array\n            {\n                return [\n                    '1' => 'email',\n                ];\n            }\n\n            /**\n             * Prepare the data for validation.\n             *\n             * @param  array  $row\n             * @param  int  $index\n             * @return array\n             */\n            public function prepareForValidation(array $row, int $index)\n            {\n                if ($index === 2) {\n                    $row[1] = 'not an email';\n                }\n\n                return $row;\n            }\n\n            /**\n             * @param  \\Maatwebsite\\Excel\\Row  $row\n             * @return void\n             */\n            public function onRow(Row $row)\n            {\n                User::query()->create([\n                    'name'     => $row[0],\n                    'email'    => $row[1],\n                    'password' => 'secret',\n                ]);\n            }\n        };\n\n        try {\n            $import->import('import-users.xlsx');\n        } catch (ValidationException $e) {\n            $this->validateFailure($e, 2, '1', [\n                'The 1( field)? must be a valid email address.',\n            ]);\n\n            $this->assertRegex(\n                '/There was an error on row 2. The 1( field)? must be a valid email address./',\n                $e->errors()[0][0]\n            );\n        }\n\n        $this->assertInstanceOf(ValidationException::class, $e ?? null);\n    }\n\n    /**\n     * @param  ValidationException  $e\n     * @param  int  $row\n     * @param  string  $attribute\n     * @param  array  $messages\n     */\n    private function validateFailure(ValidationException $e, int $row, string $attribute, array $messages)\n    {\n        $failures = $e->failures();\n        $failure  = head($failures);\n\n        $this->assertEquals($row, $failure->row());\n        $this->assertEquals($attribute, $failure->attribute());\n        $this->assertEquals($row, $failure->jsonSerialize()['row']);\n        $this->assertEquals($attribute, $failure->jsonSerialize()['attribute']);\n\n        $this->assertRegex('/' . $messages[0] . '/', $failure->errors()[0]);\n        $this->assertRegex('/' . $messages[0] . '/', $failure->jsonSerialize()['errors'][0]);\n    }\n}\n"
  },
  {
    "path": "tests/Data/Disks/.gitignore",
    "content": "*\n!.gitignore\n!Local/\n!Test/"
  },
  {
    "path": "tests/Data/Stubs/AfterQueueExportJob.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Data\\Stubs;\n\nuse Illuminate\\Bus\\Queueable;\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\n\nclass AfterQueueExportJob implements ShouldQueue\n{\n    use Queueable;\n\n    /**\n     * @var string\n     */\n    private $filePath;\n\n    /**\n     * @param  string  $filePath\n     */\n    public function __construct(string $filePath)\n    {\n        $this->filePath = $filePath;\n    }\n\n    public function handle()\n    {\n        TestCase::assertFileExists($this->filePath);\n    }\n}\n"
  },
  {
    "path": "tests/Data/Stubs/AfterQueueImportJob.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Data\\Stubs;\n\nuse Illuminate\\Bus\\Queueable;\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Illuminate\\Support\\Facades\\DB;\nuse PHPUnit\\Framework\\Assert;\n\nclass AfterQueueImportJob implements ShouldQueue\n{\n    use Queueable;\n\n    /**\n     * @var int\n     */\n    private $totalRows;\n\n    /**\n     * @param  int  $totalRows\n     */\n    public function __construct(int $totalRows)\n    {\n        $this->totalRows = $totalRows;\n    }\n\n    public function handle()\n    {\n        Assert::assertEquals($this->totalRows, DB::table('groups')->count('id'));\n    }\n}\n"
  },
  {
    "path": "tests/Data/Stubs/BeforeExportListener.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Data\\Stubs;\n\nclass BeforeExportListener\n{\n    /**\n     * @var callable\n     */\n    private $assertions;\n\n    /**\n     * @param  callable  $assertions\n     */\n    public function __construct(callable $assertions)\n    {\n        $this->assertions = $assertions;\n    }\n\n    public function __invoke()\n    {\n        ($this->assertions)(...func_get_args());\n    }\n}\n"
  },
  {
    "path": "tests/Data/Stubs/ChainedJobStub.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Data\\Stubs;\n\nuse Illuminate\\Bus\\Queueable;\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\n\nclass ChainedJobStub implements ShouldQueue\n{\n    use Queueable;\n}\n"
  },
  {
    "path": "tests/Data/Stubs/CustomConcern.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Data\\Stubs;\n\ninterface CustomConcern\n{\n    public function custom();\n}\n"
  },
  {
    "path": "tests/Data/Stubs/CustomSheetConcern.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Data\\Stubs;\n\ninterface CustomSheetConcern\n{\n    public function custom();\n}\n"
  },
  {
    "path": "tests/Data/Stubs/CustomTransactionHandler.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Data\\Stubs;\n\nuse Maatwebsite\\Excel\\Transactions\\TransactionHandler;\n\nclass CustomTransactionHandler implements TransactionHandler\n{\n    public function __invoke(callable $callback)\n    {\n        return $callback();\n    }\n}\n"
  },
  {
    "path": "tests/Data/Stubs/Database/Factories/GroupFactory.php",
    "content": "<?php\n\nuse Faker\\Generator as Faker;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database\\Group;\n\n/*\n|--------------------------------------------------------------------------\n| Model Factories\n|--------------------------------------------------------------------------\n|\n| This directory should contain each of the model factory definitions for\n| your application. Factories provide a convenient way to generate new\n| model instances for testing / seeding your application's database.\n|\n*/\n$factory->define(Group::class, function (Faker $faker) {\n    return [\n        'name' => $faker->word,\n    ];\n});\n"
  },
  {
    "path": "tests/Data/Stubs/Database/Factories/UserFactory.php",
    "content": "<?php\n\nuse Faker\\Generator as Faker;\nuse Illuminate\\Support\\Str;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database\\User;\n\n/*\n|--------------------------------------------------------------------------\n| Model Factories\n|--------------------------------------------------------------------------\n|\n| This directory should contain each of the model factory definitions for\n| your application. Factories provide a convenient way to generate new\n| model instances for testing / seeding your application's database.\n|\n*/\n$factory->define(User::class, function (Faker $faker) {\n    return [\n        'name'           => $faker->name,\n        'email'          => $faker->unique()->safeEmail,\n        'password'       => '$2y$10$TKh8H1.PfQx37YgCzwiKb.KjNyWgaHb9cbcoQgdIVFlYg7B77UdFm', // secret\n        'remember_token' => Str::random(10),\n    ];\n});\n"
  },
  {
    "path": "tests/Data/Stubs/Database/Group.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database;\n\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Database\\Eloquent\\Relations\\BelongsToMany;\n\nclass Group extends Model\n{\n    public $timestamps = false;\n\n    protected $guarded = [];\n\n    /**\n     * @return BelongsToMany\n     */\n    public function users(): BelongsToMany\n    {\n        return $this->belongsToMany(User::class);\n    }\n}\n"
  },
  {
    "path": "tests/Data/Stubs/Database/Migrations/0000_00_00_000000_create_groups_table.php",
    "content": "<?php\n\nuse Illuminate\\Database\\Migrations\\Migration;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Support\\Facades\\Schema;\n\nclass CreateGroupsTable extends Migration\n{\n    /**\n     * Run the migrations.\n     */\n    public function up()\n    {\n        Schema::create('groups', function (Blueprint $table) {\n            $table->increments('id');\n            $table->string('name');\n            $table->timestamps();\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     */\n    public function down()\n    {\n        Schema::dropIfExists('groups');\n    }\n}\n"
  },
  {
    "path": "tests/Data/Stubs/Database/Migrations/0000_00_00_000001_create_group_user_table.php",
    "content": "<?php\n\nuse Illuminate\\Database\\Migrations\\Migration;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Support\\Facades\\Schema;\n\nclass CreateGroupUserTable extends Migration\n{\n    /**\n     * Run the migrations.\n     */\n    public function up()\n    {\n        Schema::create('group_user', function (Blueprint $table) {\n            $table->increments('id');\n            $table->unsignedInteger('group_id')->index();\n            $table->unsignedInteger('user_id')->index();\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     */\n    public function down()\n    {\n        Schema::dropIfExists('group_user');\n    }\n}\n"
  },
  {
    "path": "tests/Data/Stubs/Database/Migrations/0000_00_00_000002_add_group_id_to_users_table.php",
    "content": "<?php\n\nuse Illuminate\\Database\\Migrations\\Migration;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Support\\Facades\\Schema;\n\nclass AddGroupIdToUsersTable extends Migration\n{\n    /**\n     * Run the migrations.\n     */\n    public function up()\n    {\n        Schema::table('users', function (Blueprint $table) {\n            $table->unsignedInteger('group_id')->index()->nullable();\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     */\n    public function down()\n    {\n        Schema::table('users', function (Blueprint $table) {\n            $table->dropColumn('group_id');\n        });\n    }\n}\n"
  },
  {
    "path": "tests/Data/Stubs/Database/Migrations/0000_00_00_000002_add_options_to_users.php",
    "content": "<?php\n\nuse Illuminate\\Database\\Migrations\\Migration;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Support\\Facades\\Schema;\n\nclass AddOptionsToUsers extends Migration\n{\n    /**\n     * Run the migrations.\n     */\n    public function up()\n    {\n        Schema::table('users', function (Blueprint $table) {\n            $table->text('options')->nullable();\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     */\n    public function down()\n    {\n        Schema::table('users', function (Blueprint $table) {\n            $table->dropColumn('options');\n        });\n    }\n}\n"
  },
  {
    "path": "tests/Data/Stubs/Database/User.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database;\n\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Database\\Eloquent\\Relations\\BelongsTo;\nuse Illuminate\\Database\\Eloquent\\Relations\\BelongsToMany;\nuse Laravel\\Scout\\Engines\\DatabaseEngine;\nuse Laravel\\Scout\\Engines\\Engine;\nuse Laravel\\Scout\\Engines\\NullEngine;\nuse Laravel\\Scout\\Searchable;\nuse Maatwebsite\\Excel\\Tests\\Concerns\\FromQueryTest;\nuse Maatwebsite\\Excel\\Tests\\QueuedQueryExportTest;\n\nclass User extends Model\n{\n    use Searchable;\n\n    /**\n     * @var array\n     */\n    protected $guarded = [];\n\n    /**\n     * @var array\n     */\n    protected $casts = [\n        'options' => 'array',\n    ];\n\n    /**\n     * @var array\n     */\n    protected $hidden = ['password', 'email_verified_at', 'options', 'group_id'];\n\n    public function groups(): BelongsToMany\n    {\n        return $this->belongsToMany(Group::class);\n    }\n\n    public function group(): BelongsTo\n    {\n        return $this->belongsTo(Group::class);\n    }\n\n    /**\n     * Laravel Scout under <=8 provides only\n     * — NullEngine, that is searches nothing and not applicable for tests and\n     * — AlgoliaEngine, that is 3-d party dependent and not applicable for tests too.\n     *\n     * The only test-ready engine is DatabaseEngine that comes with Scout >8\n     *\n     * Then running tests we will examine engine and skip test until DatabaseEngine is provided.\n     *\n     * @see QueuedQueryExportTest::can_queue_scout_export()\n     * @see FromQueryTest::can_export_from_scout()\n     */\n    public function searchableUsing(): Engine\n    {\n        return class_exists('\\Laravel\\Scout\\Engines\\DatabaseEngine') ? new DatabaseEngine() : new NullEngine();\n    }\n}\n"
  },
  {
    "path": "tests/Data/Stubs/EloquentCollectionWithMappingExport.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Data\\Stubs;\n\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Maatwebsite\\Excel\\Concerns\\Exportable;\nuse Maatwebsite\\Excel\\Concerns\\FromCollection;\nuse Maatwebsite\\Excel\\Concerns\\WithMapping;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database\\User;\n\nclass EloquentCollectionWithMappingExport implements FromCollection, WithMapping\n{\n    use Exportable;\n\n    /**\n     * @return Collection\n     */\n    public function collection()\n    {\n        return collect([\n            new User([\n                'firstname' => 'Patrick',\n                'lastname'  => 'Brouwers',\n            ]),\n        ]);\n    }\n\n    /**\n     * @param  User  $user\n     * @return array\n     */\n    public function map($user): array\n    {\n        return [\n            $user->firstname,\n            $user->lastname,\n        ];\n    }\n}\n"
  },
  {
    "path": "tests/Data/Stubs/EloquentLazyCollectionExport.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Data\\Stubs;\n\nuse Illuminate\\Support\\LazyCollection;\nuse Maatwebsite\\Excel\\Concerns\\Exportable;\nuse Maatwebsite\\Excel\\Concerns\\FromCollection;\n\nclass EloquentLazyCollectionExport implements FromCollection\n{\n    use Exportable;\n\n    public function collection(): LazyCollection\n    {\n        return collect([\n            [\n                'firstname' => 'Patrick',\n                'lastname'  => 'Brouwers',\n            ],\n            [\n                'firstname' => 'Patrick',\n                'lastname'  => 'Brouwers',\n            ],\n            [\n                'firstname' => 'Patrick',\n                'lastname'  => 'Brouwers',\n            ],\n            [\n                'firstname' => 'Patrick',\n                'lastname'  => 'Brouwers',\n            ],\n        ])->lazy();\n    }\n}\n"
  },
  {
    "path": "tests/Data/Stubs/EloquentLazyCollectionQueuedExport.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Data\\Stubs;\n\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Illuminate\\Support\\LazyCollection;\nuse Maatwebsite\\Excel\\Concerns\\Exportable;\nuse Maatwebsite\\Excel\\Concerns\\FromCollection;\n\nclass EloquentLazyCollectionQueuedExport implements FromCollection, ShouldQueue\n{\n    use Exportable;\n\n    public function collection(): LazyCollection\n    {\n        return collect([\n            [\n                'firstname' => 'Patrick',\n                'lastname'  => 'Brouwers',\n            ],\n            [\n                'firstname' => 'Patrick',\n                'lastname'  => 'Brouwers',\n            ],\n            [\n                'firstname' => 'Patrick',\n                'lastname'  => 'Brouwers',\n            ],\n            [\n                'firstname' => 'Patrick',\n                'lastname'  => 'Brouwers',\n            ],\n        ])->lazy();\n    }\n}\n"
  },
  {
    "path": "tests/Data/Stubs/EmptyExport.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Data\\Stubs;\n\nuse Maatwebsite\\Excel\\Concerns\\Exportable;\n\nclass EmptyExport\n{\n    use Exportable;\n}\n"
  },
  {
    "path": "tests/Data/Stubs/ExportWithEvents.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Data\\Stubs;\n\nuse Maatwebsite\\Excel\\Concerns\\Exportable;\nuse Maatwebsite\\Excel\\Concerns\\WithEvents;\nuse Maatwebsite\\Excel\\Events\\AfterSheet;\nuse Maatwebsite\\Excel\\Events\\BeforeExport;\nuse Maatwebsite\\Excel\\Events\\BeforeSheet;\nuse Maatwebsite\\Excel\\Events\\BeforeWriting;\n\nclass ExportWithEvents implements WithEvents\n{\n    use Exportable;\n\n    /**\n     * @var callable\n     */\n    public $beforeExport;\n\n    /**\n     * @var callable\n     */\n    public $beforeWriting;\n\n    /**\n     * @var callable\n     */\n    public $beforeSheet;\n\n    /**\n     * @var callable\n     */\n    public $afterSheet;\n\n    /**\n     * @return array\n     */\n    public function registerEvents(): array\n    {\n        return [\n            BeforeExport::class  => $this->beforeExport ?? function () {\n            },\n            BeforeWriting::class => $this->beforeWriting ?? function () {\n            },\n            BeforeSheet::class   => $this->beforeSheet ?? function () {\n            },\n            AfterSheet::class    => $this->afterSheet ?? function () {\n            },\n        ];\n    }\n}\n"
  },
  {
    "path": "tests/Data/Stubs/ExportWithEventsChunks.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Data\\Stubs;\n\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Maatwebsite\\Excel\\Concerns\\Exportable;\nuse Maatwebsite\\Excel\\Concerns\\FromQuery;\nuse Maatwebsite\\Excel\\Concerns\\WithCustomChunkSize;\nuse Maatwebsite\\Excel\\Concerns\\WithEvents;\nuse Maatwebsite\\Excel\\Events\\AfterChunk;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database\\User;\nuse PHPUnit\\Framework\\Assert;\n\nclass ExportWithEventsChunks implements WithEvents, FromQuery, ShouldQueue, WithCustomChunkSize\n{\n    use Exportable;\n\n    public static $calledEvent = 0;\n\n    public function registerEvents(): array\n    {\n        return [\n            AfterChunk::class => function (AfterChunk $event) {\n                ExportWithEventsChunks::$calledEvent++;\n                Assert::assertInstanceOf(ExportWithEventsChunks::class, $event->getConcernable());\n            },\n        ];\n    }\n\n    public function query(): Builder\n    {\n        return User::query();\n    }\n\n    public function chunkSize(): int\n    {\n        return 1;\n    }\n}\n"
  },
  {
    "path": "tests/Data/Stubs/ExportWithRegistersEventListeners.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Data\\Stubs;\n\nuse Maatwebsite\\Excel\\Concerns\\Exportable;\nuse Maatwebsite\\Excel\\Concerns\\RegistersEventListeners;\nuse Maatwebsite\\Excel\\Concerns\\WithEvents;\n\nclass ExportWithRegistersEventListeners implements WithEvents\n{\n    use Exportable, RegistersEventListeners;\n\n    /**\n     * @var callable\n     */\n    public static $beforeExport;\n\n    /**\n     * @var callable\n     */\n    public static $beforeWriting;\n\n    /**\n     * @var callable\n     */\n    public static $beforeSheet;\n\n    /**\n     * @var callable\n     */\n    public static $afterSheet;\n\n    public static function beforeExport()\n    {\n        (static::$beforeExport)(...func_get_args());\n    }\n\n    public static function beforeWriting()\n    {\n        (static::$beforeWriting)(...func_get_args());\n    }\n\n    public static function beforeSheet()\n    {\n        (static::$beforeSheet)(...func_get_args());\n    }\n\n    public static function afterSheet()\n    {\n        (static::$afterSheet)(...func_get_args());\n    }\n}\n"
  },
  {
    "path": "tests/Data/Stubs/FromGroupUsersQueuedQueryExport.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Data\\Stubs;\n\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Illuminate\\Database\\Eloquent\\Builder as EloquentBuilder;\nuse Illuminate\\Database\\Eloquent\\Relations\\Relation;\nuse Illuminate\\Database\\Query\\Builder;\nuse Maatwebsite\\Excel\\Concerns\\Exportable;\nuse Maatwebsite\\Excel\\Concerns\\FromQuery;\nuse Maatwebsite\\Excel\\Concerns\\WithCustomChunkSize;\nuse Maatwebsite\\Excel\\Concerns\\WithMapping;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database\\Group;\n\nclass FromGroupUsersQueuedQueryExport implements FromQuery, WithCustomChunkSize, ShouldQueue, WithMapping\n{\n    use Exportable;\n\n    /**\n     * @return Builder|EloquentBuilder|Relation\n     */\n    public function query()\n    {\n        return Group::first()->users();\n    }\n\n    /**\n     * @param  mixed  $row\n     * @return array\n     */\n    public function map($row): array\n    {\n        return [\n            $row->name,\n            $row->email,\n        ];\n    }\n\n    /**\n     * @return int\n     */\n    public function chunkSize(): int\n    {\n        return 10;\n    }\n}\n"
  },
  {
    "path": "tests/Data/Stubs/FromNestedArraysQueryExport.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Data\\Stubs;\n\nuse Illuminate\\Database\\Eloquent\\Builder as EloquentBuilder;\nuse Illuminate\\Database\\Eloquent\\Relations\\Relation;\nuse Illuminate\\Database\\Query\\Builder;\nuse Maatwebsite\\Excel\\Concerns\\Exportable;\nuse Maatwebsite\\Excel\\Concerns\\FromQuery;\nuse Maatwebsite\\Excel\\Concerns\\WithMapping;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database\\Group;\n\nclass FromNestedArraysQueryExport implements FromQuery, WithMapping\n{\n    use Exportable;\n\n    /**\n     * @return Builder|EloquentBuilder|Relation\n     */\n    public function query()\n    {\n        $query = Group::with('users');\n\n        return $query;\n    }\n\n    /**\n     * @param  Group  $row\n     * @return array\n     */\n    public function map($row): array\n    {\n        $rows    = [];\n        $sub_row = [$row->name, ''];\n        $count   = 0;\n\n        foreach ($row->users as $user) {\n            if ($count === 0) {\n                $sub_row[1] = $user['email'];\n            } else {\n                $sub_row = ['', $user['email']];\n            }\n\n            $rows[] = $sub_row;\n            $count++;\n        }\n\n        if ($count === 0) {\n            $rows[] = $sub_row;\n        }\n\n        return $rows;\n    }\n}\n"
  },
  {
    "path": "tests/Data/Stubs/FromNonEloquentQueryExport.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Data\\Stubs;\n\nuse Illuminate\\Database\\Eloquent\\Builder as EloquentBuilder;\nuse Illuminate\\Database\\Eloquent\\Relations\\Relation;\nuse Illuminate\\Database\\Query\\Builder;\nuse Illuminate\\Support\\Facades\\DB;\nuse Maatwebsite\\Excel\\Concerns\\Exportable;\nuse Maatwebsite\\Excel\\Concerns\\FromQuery;\nuse Maatwebsite\\Excel\\Concerns\\WithCustomChunkSize;\n\nclass FromNonEloquentQueryExport implements FromQuery, WithCustomChunkSize\n{\n    use Exportable;\n\n    /**\n     * @return Builder|EloquentBuilder|Relation\n     */\n    public function query()\n    {\n        return DB::table('users')->select('name')->orderBy('id');\n    }\n\n    /**\n     * @return int\n     */\n    public function chunkSize(): int\n    {\n        return 10;\n    }\n}\n"
  },
  {
    "path": "tests/Data/Stubs/FromQueryWithCustomQuerySize.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Data\\Stubs;\n\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Illuminate\\Database\\Eloquent\\Builder as EloquentBuilder;\nuse Illuminate\\Database\\Eloquent\\Relations\\Relation;\nuse Illuminate\\Database\\Query\\Builder;\nuse Illuminate\\Support\\Facades\\DB;\nuse Maatwebsite\\Excel\\Concerns\\Exportable;\nuse Maatwebsite\\Excel\\Concerns\\FromQuery;\nuse Maatwebsite\\Excel\\Concerns\\WithCustomQuerySize;\nuse Maatwebsite\\Excel\\Concerns\\WithMapping;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database\\Group;\n\nclass FromQueryWithCustomQuerySize implements FromQuery, WithCustomQuerySize, WithMapping, ShouldQueue\n{\n    use Exportable;\n\n    /**\n     * @return Builder|EloquentBuilder|Relation\n     */\n    public function query()\n    {\n        $query = Group::with('users')\n            ->join('group_user', 'groups.id', '=', 'group_user.group_id')\n            ->select('groups.*', DB::raw('count(group_user.user_id) as number_of_users'))\n            ->groupBy('groups.id')\n            ->orderBy('number_of_users');\n\n        return $query;\n    }\n\n    /**\n     * @return int\n     */\n    public function querySize(): int\n    {\n        return Group::has('users')->count();\n    }\n\n    /**\n     * @param  Group  $row\n     * @return array\n     */\n    public function map($row): array\n    {\n        return [\n            $row->id,\n            $row->name,\n            $row->number_of_users,\n        ];\n    }\n}\n"
  },
  {
    "path": "tests/Data/Stubs/FromUsersQueryExport.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Data\\Stubs;\n\nuse Illuminate\\Database\\Eloquent\\Builder as EloquentBuilder;\nuse Illuminate\\Database\\Eloquent\\Relations\\Relation;\nuse Illuminate\\Database\\Query\\Builder;\nuse Maatwebsite\\Excel\\Concerns\\Exportable;\nuse Maatwebsite\\Excel\\Concerns\\FromQuery;\nuse Maatwebsite\\Excel\\Concerns\\WithCustomChunkSize;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database\\User;\n\nclass FromUsersQueryExport implements FromQuery, WithCustomChunkSize\n{\n    use Exportable;\n\n    /**\n     * @return Builder|EloquentBuilder|Relation\n     */\n    public function query()\n    {\n        return User::query();\n    }\n\n    /**\n     * @return int\n     */\n    public function chunkSize(): int\n    {\n        return 10;\n    }\n}\n"
  },
  {
    "path": "tests/Data/Stubs/FromUsersQueryExportWithEagerLoad.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Data\\Stubs;\n\nuse Illuminate\\Database\\Eloquent\\Builder as EloquentBuilder;\nuse Illuminate\\Database\\Eloquent\\Relations\\Relation;\nuse Illuminate\\Database\\Query\\Builder;\nuse Maatwebsite\\Excel\\Concerns\\Exportable;\nuse Maatwebsite\\Excel\\Concerns\\FromQuery;\nuse Maatwebsite\\Excel\\Concerns\\WithMapping;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database\\User;\n\nclass FromUsersQueryExportWithEagerLoad implements FromQuery, WithMapping\n{\n    use Exportable;\n\n    /**\n     * @return Builder|EloquentBuilder|Relation\n     */\n    public function query()\n    {\n        return User::query()->with([\n            'groups' => function ($query) {\n                $query->where('name', 'Group 1');\n            },\n        ])->withCount('groups');\n    }\n\n    /**\n     * @param  mixed  $row\n     * @return array\n     */\n    public function map($row): array\n    {\n        return [\n            $row->name,\n            $row->groups_count,\n            $row->groups->implode('name', ', '),\n        ];\n    }\n}\n"
  },
  {
    "path": "tests/Data/Stubs/FromUsersQueryExportWithMapping.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Data\\Stubs;\n\nuse Illuminate\\Database\\Eloquent\\Builder as EloquentBuilder;\nuse Illuminate\\Database\\Eloquent\\Relations\\Relation;\nuse Illuminate\\Database\\Query\\Builder;\nuse Maatwebsite\\Excel\\Concerns\\Exportable;\nuse Maatwebsite\\Excel\\Concerns\\FromQuery;\nuse Maatwebsite\\Excel\\Concerns\\WithEvents;\nuse Maatwebsite\\Excel\\Concerns\\WithMapping;\nuse Maatwebsite\\Excel\\Events\\BeforeSheet;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database\\User;\n\nclass FromUsersQueryExportWithMapping implements FromQuery, WithMapping, WithEvents\n{\n    use Exportable;\n\n    /**\n     * @return Builder|EloquentBuilder|Relation\n     */\n    public function query()\n    {\n        return User::query();\n    }\n\n    /**\n     * @return array\n     */\n    public function registerEvents(): array\n    {\n        return [\n            BeforeSheet::class   => function (BeforeSheet $event) {\n                $event->sheet->chunkSize(10);\n            },\n        ];\n    }\n\n    /**\n     * @param  User  $row\n     * @return array\n     */\n    public function map($row): array\n    {\n        return [\n            'name' => $row->name,\n        ];\n    }\n}\n"
  },
  {
    "path": "tests/Data/Stubs/FromUsersQueryExportWithPrepareRows.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Data\\Stubs;\n\nuse Illuminate\\Database\\Eloquent\\Builder as EloquentBuilder;\nuse Illuminate\\Database\\Eloquent\\Relations\\Relation;\nuse Illuminate\\Database\\Query\\Builder;\nuse Illuminate\\Support\\Collection;\nuse Maatwebsite\\Excel\\Concerns\\Exportable;\nuse Maatwebsite\\Excel\\Concerns\\FromQuery;\nuse Maatwebsite\\Excel\\Concerns\\WithCustomChunkSize;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database\\User;\n\nclass FromUsersQueryExportWithPrepareRows implements FromQuery, WithCustomChunkSize\n{\n    use Exportable;\n\n    /**\n     * @return Builder|EloquentBuilder|Relation\n     */\n    public function query()\n    {\n        return User::query();\n    }\n\n    /**\n     * @return int\n     */\n    public function chunkSize(): int\n    {\n        return 10;\n    }\n\n    /**\n     * @param  iterable  $rows\n     * @return iterable\n     */\n    public function prepareRows($rows)\n    {\n        return (new Collection($rows))->map(function ($user) {\n            $user->name .= '_prepared_name';\n\n            return $user;\n        })->toArray();\n    }\n}\n"
  },
  {
    "path": "tests/Data/Stubs/FromUsersQueryWithJoinExport.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Data\\Stubs;\n\nuse Illuminate\\Database\\Eloquent\\Builder as EloquentBuilder;\nuse Illuminate\\Database\\Eloquent\\Relations\\Relation;\nuse Illuminate\\Database\\Query\\Builder;\nuse Maatwebsite\\Excel\\Concerns\\Exportable;\nuse Maatwebsite\\Excel\\Concerns\\FromQuery;\nuse Maatwebsite\\Excel\\Concerns\\WithCustomChunkSize;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database\\User;\n\nclass FromUsersQueryWithJoinExport implements FromQuery, WithCustomChunkSize\n{\n    use Exportable;\n\n    public $query;\n\n    public function __construct()\n    {\n        $this->query = User::query();\n    }\n\n    /**\n     * @return Builder|EloquentBuilder|Relation\n     */\n    public function query()\n    {\n        return $this->query\n            ->join(\n                'group_user',\n                'group_user.user_id',\n                '=',\n                'users.id'\n            )\n            ->select('users.*', 'group_user.group_id as gid');\n    }\n\n    /**\n     * @return int\n     */\n    public function chunkSize(): int\n    {\n        return 10;\n    }\n}\n"
  },
  {
    "path": "tests/Data/Stubs/FromUsersScoutExport.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Data\\Stubs;\n\nuse Illuminate\\Database\\Eloquent\\Builder as EloquentBuilder;\nuse Illuminate\\Database\\Eloquent\\Relations\\Relation;\nuse Illuminate\\Database\\Query\\Builder;\nuse Laravel\\Scout\\Builder as ScoutBuilder;\nuse Maatwebsite\\Excel\\Concerns\\Exportable;\nuse Maatwebsite\\Excel\\Concerns\\FromQuery;\nuse Maatwebsite\\Excel\\Concerns\\WithCustomChunkSize;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database\\User;\n\nclass FromUsersScoutExport implements FromQuery, WithCustomChunkSize\n{\n    use Exportable;\n\n    /**\n     * @return Builder|EloquentBuilder|Relation|ScoutBuilder\n     */\n    public function query()\n    {\n        return new ScoutBuilder(new User, '');\n    }\n\n    /**\n     * @return int\n     */\n    public function chunkSize(): int\n    {\n        return 10;\n    }\n}\n"
  },
  {
    "path": "tests/Data/Stubs/FromViewExportWithMultipleSheets.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Data\\Stubs;\n\nuse Illuminate\\Support\\Collection;\nuse Maatwebsite\\Excel\\Concerns\\Exportable;\nuse Maatwebsite\\Excel\\Concerns\\WithMultipleSheets;\n\nclass FromViewExportWithMultipleSheets implements WithMultipleSheets\n{\n    use Exportable;\n\n    /**\n     * @var Collection\n     */\n    protected $users;\n\n    /**\n     * @param  Collection  $users\n     */\n    public function __construct(Collection $users)\n    {\n        $this->users = $users;\n    }\n\n    /**\n     * @return SheetForUsersFromView[]\n     */\n    public function sheets(): array\n    {\n        return [\n            new SheetForUsersFromView($this->users->forPage(1, 100)),\n            new SheetForUsersFromView($this->users->forPage(2, 100)),\n            new SheetForUsersFromView($this->users->forPage(3, 100)),\n        ];\n    }\n}\n"
  },
  {
    "path": "tests/Data/Stubs/ImportWithEvents.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Data\\Stubs;\n\nuse Maatwebsite\\Excel\\Concerns\\Importable;\nuse Maatwebsite\\Excel\\Concerns\\WithEvents;\nuse Maatwebsite\\Excel\\Events\\AfterImport;\nuse Maatwebsite\\Excel\\Events\\AfterSheet;\nuse Maatwebsite\\Excel\\Events\\BeforeImport;\nuse Maatwebsite\\Excel\\Events\\BeforeSheet;\n\nclass ImportWithEvents implements WithEvents\n{\n    use Importable;\n\n    /**\n     * @var callable\n     */\n    public $beforeImport;\n\n    /**\n     * @var callable\n     */\n    public $afterImport;\n\n    /**\n     * @var callable\n     */\n    public $beforeSheet;\n\n    /**\n     * @var callable\n     */\n    public $afterSheet;\n\n    /**\n     * @return array\n     */\n    public function registerEvents(): array\n    {\n        return [\n            BeforeImport::class => $this->beforeImport ?? function () {\n            },\n            AfterImport::class => $this->afterImport ?? function () {\n            },\n            BeforeSheet::class => $this->beforeSheet ?? function () {\n            },\n            AfterSheet::class => $this->afterSheet ?? function () {\n            },\n        ];\n    }\n}\n"
  },
  {
    "path": "tests/Data/Stubs/ImportWithEventsChunksAndBatches.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Data\\Stubs;\n\nuse Maatwebsite\\Excel\\Concerns\\ToModel;\nuse Maatwebsite\\Excel\\Concerns\\WithBatchInserts;\nuse Maatwebsite\\Excel\\Concerns\\WithChunkReading;\nuse Maatwebsite\\Excel\\Events\\AfterBatch;\nuse Maatwebsite\\Excel\\Events\\AfterChunk;\n\nclass ImportWithEventsChunksAndBatches extends ImportWithEvents implements WithBatchInserts, ToModel, WithChunkReading\n{\n    /**\n     * @var callable\n     */\n    public $afterBatch;\n\n    /**\n     * @var callable\n     */\n    public $afterChunk;\n\n    /**\n     * @return array\n     */\n    public function registerEvents(): array\n    {\n        return parent::registerEvents() + [\n            AfterBatch::class => $this->afterBatch ?? function () {\n            },\n            AfterChunk::class => $this->afterChunk ?? function () {\n            },\n        ];\n    }\n\n    public function model(array $row)\n    {\n    }\n\n    public function batchSize(): int\n    {\n        return 100;\n    }\n\n    public function chunkSize(): int\n    {\n        return 500;\n    }\n}\n"
  },
  {
    "path": "tests/Data/Stubs/ImportWithRegistersEventListeners.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Data\\Stubs;\n\nuse Maatwebsite\\Excel\\Concerns\\Importable;\nuse Maatwebsite\\Excel\\Concerns\\RegistersEventListeners;\nuse Maatwebsite\\Excel\\Concerns\\WithEvents;\n\nclass ImportWithRegistersEventListeners implements WithEvents\n{\n    use Importable, RegistersEventListeners;\n\n    /**\n     * @var callable\n     */\n    public static $beforeImport;\n\n    /**\n     * @var callable\n     */\n    public static $beforeSheet;\n\n    /**\n     * @var callable\n     */\n    public static $afterSheet;\n\n    public static function beforeImport()\n    {\n        (static::$beforeImport)(...func_get_args());\n    }\n\n    public static function beforeSheet()\n    {\n        (static::$beforeSheet)(...func_get_args());\n    }\n\n    public static function afterSheet()\n    {\n        (static::$afterSheet)(...func_get_args());\n    }\n}\n"
  },
  {
    "path": "tests/Data/Stubs/QueueImportWithoutJobChaining.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Data\\Stubs;\n\nuse Maatwebsite\\Excel\\Concerns\\Importable;\nuse Maatwebsite\\Excel\\Concerns\\ShouldQueueWithoutChain;\nuse Maatwebsite\\Excel\\Concerns\\ToModel;\nuse Maatwebsite\\Excel\\Concerns\\WithChunkReading;\nuse Maatwebsite\\Excel\\Concerns\\WithEvents;\nuse Maatwebsite\\Excel\\Events\\AfterImport;\nuse Maatwebsite\\Excel\\Events\\BeforeImport;\nuse Maatwebsite\\Excel\\Reader;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database\\User;\nuse PHPUnit\\Framework\\Assert;\n\nclass QueueImportWithoutJobChaining implements ToModel, WithChunkReading, WithEvents, ShouldQueueWithoutChain\n{\n    use Importable;\n\n    public $queue;\n    public $before = false;\n    public $after  = false;\n\n    /**\n     * @param  array  $row\n     * @return Model|null\n     */\n    public function model(array $row)\n    {\n        return new User([\n            'name'     => $row[0],\n            'email'    => $row[1],\n            'password' => 'secret',\n        ]);\n    }\n\n    /**\n     * @return int\n     */\n    public function chunkSize(): int\n    {\n        return 1;\n    }\n\n    /**\n     * @return array\n     */\n    public function registerEvents(): array\n    {\n        return [\n            BeforeImport::class => function (BeforeImport $event) {\n                Assert::assertInstanceOf(Reader::class, $event->reader);\n                $this->before = true;\n            },\n            AfterImport::class  => function (AfterImport $event) {\n                Assert::assertInstanceOf(Reader::class, $event->reader);\n                $this->after = true;\n            },\n        ];\n    }\n}\n"
  },
  {
    "path": "tests/Data/Stubs/QueuedExport.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Data\\Stubs;\n\nuse Maatwebsite\\Excel\\Concerns\\Exportable;\nuse Maatwebsite\\Excel\\Concerns\\WithMultipleSheets;\n\nclass QueuedExport implements WithMultipleSheets\n{\n    use Exportable;\n\n    /**\n     * @return SheetWith100Rows[]\n     */\n    public function sheets(): array\n    {\n        return [\n            new SheetWith100Rows('A'),\n            new SheetWith100Rows('B'),\n            new SheetWith100Rows('C'),\n        ];\n    }\n}\n"
  },
  {
    "path": "tests/Data/Stubs/QueuedExportWithFailedEvents.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Data\\Stubs;\n\nuse Exception;\nuse Maatwebsite\\Excel\\Concerns\\Exportable;\nuse Maatwebsite\\Excel\\Concerns\\WithEvents;\nuse Maatwebsite\\Excel\\Concerns\\WithMultipleSheets;\nuse Maatwebsite\\Excel\\Events\\BeforeExport;\nuse PHPUnit\\Framework\\Assert;\nuse Throwable;\n\nclass QueuedExportWithFailedEvents implements WithMultipleSheets, WithEvents\n{\n    use Exportable;\n\n    /**\n     * @return SheetWith100Rows[]\n     */\n    public function sheets(): array\n    {\n        return [\n            new SheetWith100Rows('A'),\n            new SheetWith100Rows('B'),\n            new SheetWith100Rows('C'),\n        ];\n    }\n\n    /**\n     * @param  Throwable  $exception\n     */\n    public function failed(Throwable $exception)\n    {\n        Assert::assertEquals('catch exception from QueueExport job', $exception->getMessage());\n\n        app()->bind('queue-has-failed-from-queue-export-job', function () {\n            return true;\n        });\n    }\n\n    /**\n     * @return array\n     */\n    public function registerEvents(): array\n    {\n        return [\n            BeforeExport::class => function () {\n                throw new Exception('catch exception from QueueExport job');\n            },\n        ];\n    }\n}\n"
  },
  {
    "path": "tests/Data/Stubs/QueuedExportWithFailedHook.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Data\\Stubs;\n\nuse Exception;\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Maatwebsite\\Excel\\Concerns\\Exportable;\nuse Maatwebsite\\Excel\\Concerns\\FromCollection;\nuse Maatwebsite\\Excel\\Concerns\\WithMapping;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database\\User;\nuse PHPUnit\\Framework\\Assert;\n\nclass QueuedExportWithFailedHook implements FromCollection, WithMapping\n{\n    use Exportable;\n\n    /**\n     * @var bool\n     */\n    public $failed = false;\n\n    /**\n     * @return Collection\n     */\n    public function collection()\n    {\n        return collect([\n            new User([\n                'firstname' => 'Patrick',\n                'lastname'  => 'Brouwers',\n            ]),\n        ]);\n    }\n\n    /**\n     * @param  User  $user\n     * @return array\n     */\n    public function map($user): array\n    {\n        throw new Exception('we expect this');\n    }\n\n    /**\n     * @param  Exception  $exception\n     */\n    public function failed(Exception $exception)\n    {\n        Assert::assertEquals('we expect this', $exception->getMessage());\n\n        app()->bind('queue-has-failed', function () {\n            return true;\n        });\n    }\n}\n"
  },
  {
    "path": "tests/Data/Stubs/QueuedExportWithLocalePreferences.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Data\\Stubs;\n\nuse Illuminate\\Contracts\\Translation\\HasLocalePreference;\nuse Illuminate\\Support\\Collection;\nuse Maatwebsite\\Excel\\Concerns\\Exportable;\nuse Maatwebsite\\Excel\\Concerns\\FromCollection;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database\\User;\nuse PHPUnit\\Framework\\Assert;\n\nclass QueuedExportWithLocalePreferences implements FromCollection, HasLocalePreference\n{\n    use Exportable;\n\n    /**\n     * @var string\n     */\n    protected $locale;\n\n    /**\n     * QueuedExportWithLocalePreferences constructor.\n     *\n     * @param  string  $locale\n     */\n    public function __construct(string $locale)\n    {\n        $this->locale = $locale;\n    }\n\n    /**\n     * @return Collection\n     */\n    public function collection()\n    {\n        return collect([\n            new User([\n                'firstname' => 'Patrick',\n                'lastname'  => 'Brouwers',\n            ]),\n        ]);\n    }\n\n    /**\n     * @return string|null\n     */\n    public function preferredLocale()\n    {\n        return $this->locale;\n    }\n\n    /**\n     * @param  iterable  $rows\n     * @return iterable\n     */\n    public function prepareRows($rows)\n    {\n        Assert::assertEquals('ru', app()->getLocale());\n\n        app()->bind('queue-has-correct-locale', function () {\n            return true;\n        });\n\n        return $rows;\n    }\n}\n"
  },
  {
    "path": "tests/Data/Stubs/QueuedImport.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Data\\Stubs;\n\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Maatwebsite\\Excel\\Concerns\\Importable;\nuse Maatwebsite\\Excel\\Concerns\\ToModel;\nuse Maatwebsite\\Excel\\Concerns\\WithBatchInserts;\nuse Maatwebsite\\Excel\\Concerns\\WithChunkReading;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database\\Group;\n\nclass QueuedImport implements ShouldQueue, ToModel, WithChunkReading, WithBatchInserts\n{\n    use Importable;\n\n    /**\n     * @param  array  $row\n     * @return Model|null\n     */\n    public function model(array $row)\n    {\n        return new Group([\n            'name' => $row[0],\n        ]);\n    }\n\n    /**\n     * @return int\n     */\n    public function batchSize(): int\n    {\n        return 100;\n    }\n\n    /**\n     * @return int\n     */\n    public function chunkSize(): int\n    {\n        return 100;\n    }\n}\n"
  },
  {
    "path": "tests/Data/Stubs/QueuedImportWithFailure.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Data\\Stubs;\n\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Maatwebsite\\Excel\\Concerns\\Importable;\nuse Maatwebsite\\Excel\\Concerns\\ToModel;\nuse Maatwebsite\\Excel\\Concerns\\WithChunkReading;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database\\Group;\n\nclass QueuedImportWithFailure implements ShouldQueue, ToModel, WithChunkReading\n{\n    use Importable;\n\n    /**\n     * @param  array  $row\n     * @return Model|null\n     */\n    public function model(array $row)\n    {\n        throw new \\Exception('Something went wrong in the chunk');\n\n        return new Group([\n            'name' => $row[0],\n        ]);\n    }\n\n    /**\n     * @return int\n     */\n    public function chunkSize(): int\n    {\n        return 100;\n    }\n}\n"
  },
  {
    "path": "tests/Data/Stubs/QueuedImportWithMiddleware.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Data\\Stubs;\n\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Maatwebsite\\Excel\\Concerns\\Importable;\nuse Maatwebsite\\Excel\\Concerns\\ToModel;\nuse Maatwebsite\\Excel\\Concerns\\WithChunkReading;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database\\Group;\n\nclass QueuedImportWithMiddleware implements ShouldQueue, ToModel, WithChunkReading\n{\n    use Importable;\n\n    /**\n     * @param  array  $row\n     * @return Model|null\n     */\n    public function model(array $row)\n    {\n        return new Group([\n            'name' => $row[0],\n        ]);\n    }\n\n    public function middleware()\n    {\n        return [function () {\n            throw new \\Exception('Job reached middleware method');\n        }];\n    }\n\n    /**\n     * @return int\n     */\n    public function chunkSize(): int\n    {\n        return 100;\n    }\n}\n"
  },
  {
    "path": "tests/Data/Stubs/QueuedImportWithRetryUntil.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Data\\Stubs;\n\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Maatwebsite\\Excel\\Concerns\\Importable;\nuse Maatwebsite\\Excel\\Concerns\\ToModel;\nuse Maatwebsite\\Excel\\Concerns\\WithChunkReading;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database\\Group;\n\nclass QueuedImportWithRetryUntil implements ShouldQueue, ToModel, WithChunkReading\n{\n    use Importable;\n\n    /**\n     * @param  array  $row\n     * @return Model|null\n     */\n    public function model(array $row)\n    {\n        return new Group([\n            'name' => $row[0],\n        ]);\n    }\n\n    /**\n     * @return int\n     */\n    public function chunkSize(): int\n    {\n        return 100;\n    }\n\n    /**\n     * Determine the time at which the job should timeout.\n     *\n     * @return \\DateTime\n     */\n    public function retryUntil()\n    {\n        throw new \\Exception('Job reached retryUntil method');\n\n        return now()->addSeconds(5);\n    }\n}\n"
  },
  {
    "path": "tests/Data/Stubs/SheetForUsersFromView.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Data\\Stubs;\n\nuse Illuminate\\Contracts\\View\\View;\nuse Illuminate\\Support\\Collection;\nuse Maatwebsite\\Excel\\Concerns\\Exportable;\nuse Maatwebsite\\Excel\\Concerns\\FromView;\n\nclass SheetForUsersFromView implements FromView\n{\n    use Exportable;\n\n    /**\n     * @var Collection\n     */\n    protected $users;\n\n    /**\n     * @param  Collection  $users\n     */\n    public function __construct(Collection $users)\n    {\n        $this->users = $users;\n    }\n\n    /**\n     * @return View\n     */\n    public function view(): View\n    {\n        return view('users', [\n            'users' => $this->users,\n        ]);\n    }\n}\n"
  },
  {
    "path": "tests/Data/Stubs/SheetWith100Rows.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Data\\Stubs;\n\nuse Illuminate\\Support\\Collection;\nuse Maatwebsite\\Excel\\Concerns\\Exportable;\nuse Maatwebsite\\Excel\\Concerns\\FromCollection;\nuse Maatwebsite\\Excel\\Concerns\\RegistersEventListeners;\nuse Maatwebsite\\Excel\\Concerns\\ShouldAutoSize;\nuse Maatwebsite\\Excel\\Concerns\\WithEvents;\nuse Maatwebsite\\Excel\\Concerns\\WithTitle;\nuse Maatwebsite\\Excel\\Events\\BeforeWriting;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\nuse Maatwebsite\\Excel\\Writer;\n\nclass SheetWith100Rows implements FromCollection, WithTitle, ShouldAutoSize, WithEvents\n{\n    use Exportable, RegistersEventListeners;\n\n    /**\n     * @var string\n     */\n    private $title;\n\n    /**\n     * @param  string  $title\n     */\n    public function __construct(string $title)\n    {\n        $this->title = $title;\n    }\n\n    /**\n     * @return Collection\n     */\n    public function collection()\n    {\n        $collection = new Collection;\n        for ($i = 0; $i < 100; $i++) {\n            $row = new Collection();\n            for ($j = 0; $j < 5; $j++) {\n                $row[] = $this->title() . '-' . $i . '-' . $j;\n            }\n\n            $collection->push($row);\n        }\n\n        return $collection;\n    }\n\n    /**\n     * @return string\n     */\n    public function title(): string\n    {\n        return $this->title;\n    }\n\n    /**\n     * @param  BeforeWriting  $event\n     */\n    public static function beforeWriting(BeforeWriting $event)\n    {\n        TestCase::assertInstanceOf(Writer::class, $event->writer);\n    }\n}\n"
  },
  {
    "path": "tests/Data/Stubs/ShouldQueueExport.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Data\\Stubs;\n\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Maatwebsite\\Excel\\Concerns\\Exportable;\nuse Maatwebsite\\Excel\\Concerns\\WithMultipleSheets;\n\nclass ShouldQueueExport implements WithMultipleSheets, ShouldQueue\n{\n    use Exportable;\n\n    /**\n     * @return SheetWith100Rows[]\n     */\n    public function sheets(): array\n    {\n        return [\n            new SheetWith100Rows('A'),\n            new SheetWith100Rows('B'),\n            new SheetWith100Rows('C'),\n        ];\n    }\n}\n"
  },
  {
    "path": "tests/Data/Stubs/Views/users.blade.php",
    "content": "<table>\n    <thead>\n    <tr>\n        <th>Name</th>\n        <th>Email</th>\n    </tr>\n    </thead>\n    <tbody>\n    @foreach($users as $user)\n        <tr>\n            <td>{{ $user->name }}</td>\n            <td>{{ $user->email }}</td>\n        </tr>\n    @endforeach\n    </tbody>\n</table>"
  },
  {
    "path": "tests/Data/Stubs/WithMappingExport.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Data\\Stubs;\n\nuse Illuminate\\Support\\Collection;\nuse Maatwebsite\\Excel\\Concerns\\Exportable;\nuse Maatwebsite\\Excel\\Concerns\\FromCollection;\nuse Maatwebsite\\Excel\\Concerns\\WithMapping;\n\nclass WithMappingExport implements FromCollection, WithMapping\n{\n    use Exportable;\n\n    /**\n     * @return Collection\n     */\n    public function collection()\n    {\n        return collect([\n            ['A1', 'B1', 'C1'],\n            ['A2', 'B2', 'C2'],\n        ]);\n    }\n\n    /**\n     * @param  mixed  $row\n     * @return array\n     */\n    public function map($row): array\n    {\n        return [\n            'mapped-' . $row[0],\n            'mapped-' . $row[1],\n            'mapped-' . $row[2],\n        ];\n    }\n}\n"
  },
  {
    "path": "tests/Data/Stubs/WithTitleExport.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Data\\Stubs;\n\nuse Maatwebsite\\Excel\\Concerns\\Exportable;\nuse Maatwebsite\\Excel\\Concerns\\WithTitle;\n\nclass WithTitleExport implements WithTitle\n{\n    use Exportable;\n\n    /**\n     * @return string\n     */\n    public function title(): string\n    {\n        return 'given-title';\n    }\n}\n"
  },
  {
    "path": "tests/DelegatedMacroableTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests;\n\nuse Maatwebsite\\Excel\\Concerns\\Exportable;\nuse Maatwebsite\\Excel\\Concerns\\RegistersEventListeners;\nuse Maatwebsite\\Excel\\Concerns\\WithEvents;\nuse Maatwebsite\\Excel\\Events\\BeforeExport;\nuse Maatwebsite\\Excel\\Events\\BeforeSheet;\nuse Maatwebsite\\Excel\\Sheet;\nuse Maatwebsite\\Excel\\Writer;\nuse PhpOffice\\PhpSpreadsheet\\Document\\Properties;\n\nclass DelegatedMacroableTest extends TestCase\n{\n    public function test_can_call_methods_from_delegate()\n    {\n        $export = new class implements WithEvents\n        {\n            use RegistersEventListeners, Exportable;\n\n            public static function beforeExport(BeforeExport $event)\n            {\n                // ->getProperties() will be called via __call on the ->getDelegate()\n                TestCase::assertInstanceOf(Properties::class, $event->writer->getProperties());\n            }\n        };\n\n        $export->download('some-file.xlsx');\n    }\n\n    public function test_can_use_writer_macros()\n    {\n        $called = false;\n        Writer::macro('test', function () use (&$called) {\n            $called = true;\n        });\n\n        $export = new class implements WithEvents\n        {\n            use RegistersEventListeners, Exportable;\n\n            public static function beforeExport(BeforeExport $event)\n            {\n                // call macro method\n                $event->writer->test();\n            }\n        };\n\n        $export->download('some-file.xlsx');\n\n        $this->assertTrue($called);\n    }\n\n    public function test_can_use_sheet_macros()\n    {\n        $called = false;\n        Sheet::macro('test', function () use (&$called) {\n            $called = true;\n        });\n\n        $export = new class implements WithEvents\n        {\n            use RegistersEventListeners, Exportable;\n\n            public static function beforeSheet(BeforeSheet $event)\n            {\n                // call macro method\n                $event->sheet->test();\n            }\n        };\n\n        $export->download('some-file.xlsx');\n\n        $this->assertTrue($called);\n    }\n}\n"
  },
  {
    "path": "tests/ExcelFakeTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests;\n\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Foundation\\Bus\\PendingDispatch;\nuse Illuminate\\Support\\Collection;\nuse Maatwebsite\\Excel\\Concerns\\FromCollection;\nuse Maatwebsite\\Excel\\Concerns\\ToModel;\nuse Maatwebsite\\Excel\\Facades\\Excel as ExcelFacade;\nuse Maatwebsite\\Excel\\Fakes\\ExcelFake;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\ChainedJobStub;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database\\User;\nuse Symfony\\Component\\HttpFoundation\\BinaryFileResponse;\n\nclass ExcelFakeTest extends TestCase\n{\n    public function test_can_fake_an_export()\n    {\n        ExcelFacade::fake();\n\n        // Excel instance should be swapped to the fake now.\n        $this->assertInstanceOf(ExcelFake::class, $this->app->make('excel'));\n    }\n\n    public function test_can_assert_against_a_fake_downloaded_export()\n    {\n        ExcelFacade::fake();\n\n        $response = ExcelFacade::download($this->givenExport(), 'downloaded-filename.csv');\n\n        $this->assertInstanceOf(BinaryFileResponse::class, $response);\n\n        ExcelFacade::assertDownloaded('downloaded-filename.csv');\n        ExcelFacade::assertDownloaded('downloaded-filename.csv', function (FromCollection $export) {\n            return $export->collection()->contains('foo');\n        });\n        ExcelFacade::matchByRegex();\n        ExcelFacade::assertDownloaded('/\\w{10}-\\w{8}\\.csv/');\n    }\n\n    public function test_can_assert_against_a_fake_stored_export()\n    {\n        ExcelFacade::fake();\n\n        $response = ExcelFacade::store($this->givenExport(), 'stored-filename.csv', 's3');\n\n        $this->assertTrue($response);\n\n        ExcelFacade::assertStored('stored-filename.csv', 's3');\n        ExcelFacade::assertStored('stored-filename.csv', 's3', function (FromCollection $export) {\n            return $export->collection()->contains('foo');\n        });\n        ExcelFacade::matchByRegex();\n        ExcelFacade::assertStored('/\\w{6}-\\w{8}\\.csv/', 's3');\n    }\n\n    public function test_can_assert_regex_against_a_fake_stored_export_with_multiple_files()\n    {\n        ExcelFacade::fake();\n\n        $response = ExcelFacade::store($this->givenExport(), 'stored-filename-one.csv', 's3');\n\n        $this->assertTrue($response);\n\n        $response = ExcelFacade::store($this->givenExport(), 'stored-filename-two.csv', 's3');\n\n        $this->assertTrue($response);\n\n        ExcelFacade::matchByRegex();\n        ExcelFacade::assertStored('/\\w{6}-\\w{8}-one\\.csv/', 's3');\n        ExcelFacade::assertStored('/\\w{6}-\\w{8}-two\\.csv/', 's3');\n    }\n\n    public function test_a_callback_can_be_passed_as_the_second_argument_when_asserting_against_a_faked_stored_export()\n    {\n        ExcelFacade::fake();\n\n        $response = ExcelFacade::store($this->givenExport(), 'stored-filename.csv');\n\n        $this->assertTrue($response);\n\n        ExcelFacade::assertStored('stored-filename.csv');\n        ExcelFacade::assertStored('stored-filename.csv', function (FromCollection $export) {\n            return $export->collection()->contains('foo');\n        });\n        ExcelFacade::matchByRegex();\n        ExcelFacade::assertStored('/\\w{6}-\\w{8}\\.csv/');\n    }\n\n    public function test_can_assert_against_a_fake_queued_export()\n    {\n        ExcelFacade::fake();\n\n        $response = ExcelFacade::queue($this->givenExport(), 'queued-filename.csv', 's3');\n\n        $this->assertInstanceOf(PendingDispatch::class, $response);\n\n        ExcelFacade::assertQueued('queued-filename.csv', 's3');\n        ExcelFacade::assertQueued('queued-filename.csv', 's3', function (FromCollection $export) {\n            return $export->collection()->contains('foo');\n        });\n        ExcelFacade::matchByRegex();\n        ExcelFacade::assertQueued('/\\w{6}-\\w{8}\\.csv/', 's3');\n    }\n\n    public function test_can_assert_against_a_fake_implicitly_queued_export()\n    {\n        ExcelFacade::fake();\n\n        $response = ExcelFacade::store($this->givenQueuedExport(), 'queued-filename.csv', 's3');\n\n        $this->assertInstanceOf(PendingDispatch::class, $response);\n\n        ExcelFacade::assertStored('queued-filename.csv', 's3');\n        ExcelFacade::assertQueued('queued-filename.csv', 's3');\n        ExcelFacade::assertQueued('queued-filename.csv', 's3', function (FromCollection $export) {\n            return $export->collection()->contains('foo');\n        });\n        ExcelFacade::matchByRegex();\n        ExcelFacade::assertQueued('/\\w{6}-\\w{8}\\.csv/', 's3');\n    }\n\n    public function test_can_assert_against_a_fake_queued_export_with_chain()\n    {\n        ExcelFacade::fake();\n\n        ExcelFacade::queue(\n            $this->givenQueuedExport(), 'queued-filename.csv', 's3'\n        )->chain([\n            new ChainedJobStub(),\n        ]);\n\n        ExcelFacade::assertQueuedWithChain([\n            new ChainedJobStub(),\n        ]);\n    }\n\n    public function test_can_assert_against_a_fake_raw_export()\n    {\n        ExcelFacade::fake();\n\n        $response = ExcelFacade::raw($this->givenExport(), \\Maatwebsite\\Excel\\Excel::XLSX);\n\n        $this->assertIsString($response);\n\n        ExcelFacade::assertExportedInRaw(get_class($this->givenExport()));\n        ExcelFacade::assertExportedInRaw(get_class($this->givenExport()), function (FromCollection $export) {\n            return $export->collection()->contains('foo');\n        });\n    }\n\n    public function test_can_assert_against_a_fake_import()\n    {\n        ExcelFacade::fake();\n\n        ExcelFacade::import($this->givenImport(), 'stored-filename.csv', 's3');\n\n        ExcelFacade::assertImported('stored-filename.csv', 's3');\n        ExcelFacade::assertImported('stored-filename.csv', 's3', function (ToModel $import) {\n            return $import->model([]) instanceof User;\n        });\n        ExcelFacade::matchByRegex();\n        ExcelFacade::assertImported('/\\w{6}-\\w{8}\\.csv/', 's3');\n    }\n\n    public function test_can_assert_against_a_fake_import_with_uploaded_file()\n    {\n        ExcelFacade::fake();\n\n        ExcelFacade::import($this->givenImport(), $this->givenUploadedFile(__DIR__ . '/Data/Disks/Local/import.xlsx'));\n\n        ExcelFacade::assertImported('import.xlsx');\n        ExcelFacade::assertImported('import.xlsx', function (ToModel $import) {\n            return $import->model([]) instanceof User;\n        });\n        ExcelFacade::matchByRegex();\n        ExcelFacade::assertImported('/\\w{6}\\.xlsx/');\n    }\n\n    public function test_can_assert_against_a_fake_queued_import()\n    {\n        ExcelFacade::fake();\n\n        $response = ExcelFacade::queueImport($this->givenQueuedImport(), 'queued-filename.csv', 's3');\n\n        $this->assertInstanceOf(PendingDispatch::class, $response);\n\n        ExcelFacade::assertImported('queued-filename.csv', 's3');\n        ExcelFacade::assertQueued('queued-filename.csv', 's3');\n        ExcelFacade::assertQueued('queued-filename.csv', 's3', function (ToModel $import) {\n            return $import->model([]) instanceof User;\n        });\n        ExcelFacade::matchByRegex();\n        ExcelFacade::assertQueued('/\\w{6}-\\w{8}\\.csv/', 's3');\n    }\n\n    public function test_can_assert_against_a_fake_implicitly_queued_import()\n    {\n        ExcelFacade::fake();\n\n        $response = ExcelFacade::import($this->givenQueuedImport(), 'queued-filename.csv', 's3');\n\n        $this->assertInstanceOf(PendingDispatch::class, $response);\n\n        ExcelFacade::assertImported('queued-filename.csv', 's3');\n        ExcelFacade::assertQueued('queued-filename.csv', 's3');\n        ExcelFacade::assertQueued('queued-filename.csv', 's3', function (ToModel $import) {\n            return $import->model([]) instanceof User;\n        });\n        ExcelFacade::matchByRegex();\n        ExcelFacade::assertQueued('/\\w{6}-\\w{8}\\.csv/', 's3');\n    }\n\n    public function test_can_assert_against_a_fake_queued_import_with_chain()\n    {\n        ExcelFacade::fake();\n\n        ExcelFacade::queueImport(\n            $this->givenQueuedImport(), 'queued-filename.csv', 's3'\n        )->chain([\n            new ChainedJobStub(),\n        ]);\n\n        ExcelFacade::assertQueuedWithChain([\n            new ChainedJobStub(),\n        ]);\n    }\n\n    public function test_a_callback_can_be_passed_as_the_second_argument_when_asserting_against_a_faked_queued_export()\n    {\n        ExcelFacade::fake();\n\n        $response = ExcelFacade::queue($this->givenExport(), 'queued-filename.csv');\n\n        $this->assertInstanceOf(PendingDispatch::class, $response);\n\n        ExcelFacade::assertQueued('queued-filename.csv');\n        ExcelFacade::assertQueued('queued-filename.csv', function (FromCollection $export) {\n            return $export->collection()->contains('foo');\n        });\n        ExcelFacade::matchByRegex();\n        ExcelFacade::assertQueued('/\\w{6}-\\w{8}\\.csv/');\n    }\n\n    /**\n     * @return FromCollection\n     */\n    private function givenExport()\n    {\n        return new class implements FromCollection\n        {\n            /**\n             * @return Collection\n             */\n            public function collection()\n            {\n                return collect(['foo', 'bar']);\n            }\n        };\n    }\n\n    /**\n     * @return FromCollection\n     */\n    private function givenQueuedExport()\n    {\n        return new class implements FromCollection, ShouldQueue\n        {\n            /**\n             * @return Collection\n             */\n            public function collection()\n            {\n                return collect(['foo', 'bar']);\n            }\n        };\n    }\n\n    /**\n     * @return object\n     */\n    private function givenImport()\n    {\n        return new class implements ToModel\n        {\n            /**\n             * @param  array  $row\n             * @return Model|null\n             */\n            public function model(array $row)\n            {\n                return new User([]);\n            }\n        };\n    }\n\n    /**\n     * @return object\n     */\n    private function givenQueuedImport()\n    {\n        return new class implements ToModel, ShouldQueue\n        {\n            /**\n             * @param  array  $row\n             * @return Model|null\n             */\n            public function model(array $row)\n            {\n                return new User([]);\n            }\n        };\n    }\n}\n"
  },
  {
    "path": "tests/ExcelServiceProviderTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests;\n\nuse Composer\\InstalledVersions;\nuse Composer\\Semver\\VersionParser;\nuse Illuminate\\Contracts\\Console\\Kernel;\nuse Maatwebsite\\Excel\\Cache\\MemoryCache;\nuse Maatwebsite\\Excel\\Cache\\MemoryCacheDeprecated;\nuse Maatwebsite\\Excel\\Excel;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\CustomTransactionHandler;\nuse Maatwebsite\\Excel\\Transactions\\TransactionManager;\nuse PhpOffice\\PhpSpreadsheet\\Settings;\n\nclass ExcelServiceProviderTest extends TestCase\n{\n    public function test_custom_transaction_handler_is_bound()\n    {\n        $this->app->make(TransactionManager::class)->extend('handler', function () {\n            return new CustomTransactionHandler;\n        });\n\n        $this->assertInstanceOf(CustomTransactionHandler::class, $this->app->make(TransactionManager::class)->driver('handler'));\n    }\n\n    public function test_is_bound()\n    {\n        $this->assertTrue($this->app->bound('excel'));\n    }\n\n    public function test_has_aliased()\n    {\n        $this->assertTrue($this->app->isAlias(Excel::class));\n        $this->assertEquals('excel', $this->app->getAlias(Excel::class));\n    }\n\n    public function test_registers_console_commands()\n    {\n        /** @var Kernel $kernel */\n        $kernel   = $this->app->make(Kernel::class);\n        $commands = $kernel->all();\n\n        $this->assertArrayHasKey('make:export', $commands);\n        $this->assertArrayHasKey('make:import', $commands);\n    }\n\n    public function test_sets_php_spreadsheet_settings()\n    {\n        $driver = config('excel.cache.driver');\n\n        $this->assertEquals('memory', $driver);\n\n        if (InstalledVersions::satisfies(new VersionParser, 'psr/simple-cache', '^3.0')) {\n            $this->assertInstanceOf(\n                MemoryCache::class,\n                Settings::getCache()\n            );\n        } else {\n            $this->assertInstanceOf(\n                MemoryCacheDeprecated::class,\n                Settings::getCache()\n            );\n        }\n    }\n}\n"
  },
  {
    "path": "tests/ExcelTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests;\n\nuse Illuminate\\Contracts\\View\\View;\nuse Illuminate\\Http\\UploadedFile;\nuse Illuminate\\Support\\Collection;\nuse Maatwebsite\\Excel\\Concerns\\Exportable;\nuse Maatwebsite\\Excel\\Concerns\\FromCollection;\nuse Maatwebsite\\Excel\\Concerns\\FromView;\nuse Maatwebsite\\Excel\\Concerns\\Importable;\nuse Maatwebsite\\Excel\\Concerns\\RegistersEventListeners;\nuse Maatwebsite\\Excel\\Concerns\\ToArray;\nuse Maatwebsite\\Excel\\Concerns\\WithCustomCsvSettings;\nuse Maatwebsite\\Excel\\Concerns\\WithEvents;\nuse Maatwebsite\\Excel\\Excel;\nuse Maatwebsite\\Excel\\Facades\\Excel as ExcelFacade;\nuse Maatwebsite\\Excel\\Importer;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\EmptyExport;\nuse Maatwebsite\\Excel\\Tests\\Helpers\\FileHelper;\nuse PHPUnit\\Framework\\Assert;\nuse Symfony\\Component\\HttpFoundation\\BinaryFileResponse;\n\nclass ExcelTest extends TestCase\n{\n    /**\n     * @var Excel\n     */\n    protected $SUT;\n\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $this->SUT = $this->app->make(Excel::class);\n    }\n\n    public function test_can_download_an_export_object_with_facade()\n    {\n        $export = new EmptyExport();\n\n        $response = ExcelFacade::download($export, 'filename.xlsx');\n\n        $this->assertInstanceOf(BinaryFileResponse::class, $response);\n        $this->assertEquals('attachment; filename=filename.xlsx', str_replace('\"', '', $response->headers->get('Content-Disposition')));\n    }\n\n    public function test_can_download_an_export_object()\n    {\n        $export = new EmptyExport();\n\n        $response = $this->SUT->download($export, 'filename.xlsx');\n\n        $this->assertInstanceOf(BinaryFileResponse::class, $response);\n        $this->assertEquals('attachment; filename=filename.xlsx', str_replace('\"', '', $response->headers->get('Content-Disposition')));\n    }\n\n    public function test_can_store_an_export_object_on_default_disk()\n    {\n        $export = new EmptyExport;\n        $name   = 'filename.xlsx';\n        $path   = FileHelper::absolutePath($name, 'local');\n\n        @unlink($path);\n\n        $this->assertFileMissing($path);\n\n        $response = $this->SUT->store($export, $name);\n\n        $this->assertTrue($response);\n        $this->assertFileExists($path);\n    }\n\n    public function test_can_store_an_export_object_on_another_disk()\n    {\n        $export = new EmptyExport;\n        $name   = 'filename.xlsx';\n        $path   = FileHelper::absolutePath($name, 'test');\n\n        @unlink($path);\n\n        $this->assertFileMissing($path);\n\n        $response = $this->SUT->store($export, $name, 'test');\n\n        $this->assertTrue($response);\n        $this->assertFileExists($path);\n    }\n\n    public function test_can_store_csv_export_with_default_settings()\n    {\n        $export = new EmptyExport;\n        $name   = 'filename.csv';\n        $path   = FileHelper::absolutePath($name, 'local');\n\n        @unlink($path);\n\n        $this->assertFileMissing($path);\n\n        $response = $this->SUT->store($export, $name);\n\n        $this->assertTrue($response);\n        $this->assertFileExists($path);\n    }\n\n    public function test_can_get_raw_export_contents()\n    {\n        $export = new EmptyExport;\n\n        $response = $this->SUT->raw($export, Excel::XLSX);\n\n        $this->assertNotEmpty($response);\n    }\n\n    public function test_can_store_tsv_export_with_default_settings()\n    {\n        $export = new EmptyExport;\n        $name   = 'filename.tsv';\n        $path   = FileHelper::absolutePath($name, 'local');\n\n        @unlink($path);\n\n        $this->assertFileMissing($path);\n\n        $response = $this->SUT->store($export, $name);\n\n        $this->assertTrue($response);\n        $this->assertFileExists($path);\n    }\n\n    public function test_can_store_csv_export_with_custom_settings()\n    {\n        $export = new class implements WithEvents, FromCollection, WithCustomCsvSettings\n        {\n            use RegistersEventListeners;\n\n            /**\n             * @return Collection\n             */\n            public function collection()\n            {\n                return collect([\n                    ['A1', 'B1'],\n                    ['A2', 'B2'],\n                ]);\n            }\n\n            /**\n             * @return array\n             */\n            public function getCsvSettings(): array\n            {\n                return [\n                    'line_ending'            => PHP_EOL,\n                    'enclosure'              => '\"',\n                    'delimiter'              => ';',\n                    'include_separator_line' => true,\n                    'excel_compatibility'    => false,\n                ];\n            }\n        };\n\n        $this->SUT->store($export, 'filename.csv');\n\n        $contents = file_get_contents(__DIR__ . '/Data/Disks/Local/filename.csv');\n\n        $this->assertStringContains('sep=;', $contents);\n        $this->assertStringContains('\"A1\";\"B1\"', $contents);\n        $this->assertStringContains('\"A2\";\"B2\"', $contents);\n    }\n\n    public function test_cannot_use_from_collection_and_from_view_on_same_export()\n    {\n        $this->expectException(\\Maatwebsite\\Excel\\Exceptions\\ConcernConflictException::class);\n        $this->expectExceptionMessage('Cannot use FromQuery, FromArray or FromCollection and FromView on the same sheet');\n\n        $export = new class implements FromCollection, FromView\n        {\n            use Exportable;\n\n            /**\n             * @return Collection\n             */\n            public function collection()\n            {\n                return collect();\n            }\n\n            /**\n             * @return View\n             */\n            public function view(): View\n            {\n                return view('users');\n            }\n        };\n\n        $export->download('filename.csv');\n    }\n\n    public function test_can_import_a_simple_xlsx_file_to_array()\n    {\n        $import = new class\n        {\n            use Importable;\n        };\n\n        $this->assertEquals([\n            [\n                ['test', 'test'],\n                ['test', 'test'],\n            ],\n        ], $import->toArray('import.xlsx'));\n    }\n\n    public function test_can_import_a_simple_xlsx_file_to_collection()\n    {\n        $import = new class\n        {\n            use Importable;\n        };\n\n        $this->assertEquals(new Collection([\n            new Collection([\n                new Collection(['test', 'test']),\n                new Collection(['test', 'test']),\n            ]),\n        ]), $import->toCollection('import.xlsx'));\n    }\n\n    public function test_can_import_a_simple_xlsx_file_to_collection_without_import_object()\n    {\n        $this->assertEquals(new Collection([\n            new Collection([\n                new Collection(['test', 'test']),\n                new Collection(['test', 'test']),\n            ]),\n        ]), ExcelFacade::toCollection(null, 'import.xlsx'));\n    }\n\n    public function test_can_import_a_simple_xlsx_file()\n    {\n        $import = new class implements ToArray\n        {\n            /**\n             * @param  array  $array\n             */\n            public function array(array $array)\n            {\n                Assert::assertEquals([\n                    ['test', 'test'],\n                    ['test', 'test'],\n                ], $array);\n            }\n        };\n\n        $imported = $this->SUT->import($import, 'import.xlsx');\n\n        $this->assertInstanceOf(Importer::class, $imported);\n    }\n\n    public function test_can_import_a_tsv_file()\n    {\n        $import = new class implements ToArray, WithCustomCsvSettings\n        {\n            /**\n             * @param  array  $array\n             */\n            public function array(array $array)\n            {\n                Assert::assertEquals([\n                    'tconst',\n                    'titleType',\n                    'primaryTitle',\n                    'originalTitle',\n                    'isAdult',\n                    'startYear',\n                    'endYear',\n                    'runtimeMinutes',\n                    'genres',\n                ], $array[0]);\n            }\n\n            /**\n             * @return array\n             */\n            public function getCsvSettings(): array\n            {\n                return [\n                    'delimiter' => \"\\t\",\n                ];\n            }\n        };\n\n        $imported = $this->SUT->import($import, 'import-titles.tsv');\n\n        $this->assertInstanceOf(Importer::class, $imported);\n    }\n\n    public function test_can_chain_imports()\n    {\n        $import1 = new class implements ToArray\n        {\n            /**\n             * @param  array  $array\n             */\n            public function array(array $array)\n            {\n                Assert::assertEquals([\n                    ['test', 'test'],\n                    ['test', 'test'],\n                ], $array);\n            }\n        };\n\n        $import2 = new class implements ToArray\n        {\n            /**\n             * @param  array  $array\n             */\n            public function array(array $array)\n            {\n                Assert::assertEquals([\n                    ['test', 'test'],\n                    ['test', 'test'],\n                ], $array);\n            }\n        };\n\n        $imported = $this->SUT\n            ->import($import1, 'import.xlsx')\n            ->import($import2, 'import.xlsx');\n\n        $this->assertInstanceOf(Importer::class, $imported);\n    }\n\n    public function test_can_import_a_simple_xlsx_file_from_uploaded_file()\n    {\n        $import = new class implements ToArray\n        {\n            /**\n             * @param  array  $array\n             */\n            public function array(array $array)\n            {\n                Assert::assertEquals([\n                    ['test', 'test'],\n                    ['test', 'test'],\n                ], $array);\n            }\n        };\n\n        $this->SUT->import($import, $this->givenUploadedFile(__DIR__ . '/Data/Disks/Local/import.xlsx'));\n    }\n\n    public function test_can_import_a_simple_xlsx_file_from_real_path()\n    {\n        $import = new class implements ToArray\n        {\n            /**\n             * @param  array  $array\n             */\n            public function array(array $array)\n            {\n                Assert::assertEquals([\n                    ['test', 'test'],\n                    ['test', 'test'],\n                ], $array);\n            }\n        };\n\n        $this->SUT->import($import, __DIR__ . '/Data/Disks/Local/import.xlsx');\n    }\n\n    public function test_import_will_throw_error_when_no_reader_type_could_be_detected_when_no_extension()\n    {\n        $this->expectException(\\Maatwebsite\\Excel\\Exceptions\\NoTypeDetectedException::class);\n\n        $import = new class implements ToArray\n        {\n            /**\n             * @param  array  $array\n             */\n            public function array(array $array)\n            {\n                Assert::assertEquals([\n                    ['test', 'test'],\n                    ['test', 'test'],\n                ], $array);\n            }\n        };\n\n        $this->SUT->import($import, UploadedFile::fake()->create('import'));\n    }\n\n    public function test_import_will_throw_error_when_no_reader_type_could_be_detected_with_unknown_extension()\n    {\n        $this->expectException(\\Maatwebsite\\Excel\\Exceptions\\NoTypeDetectedException::class);\n\n        $import = new class implements ToArray\n        {\n            /**\n             * @param  array  $array\n             */\n            public function array(array $array)\n            {\n                //\n            }\n        };\n\n        $this->SUT->import($import, 'unknown-reader-type.zip');\n    }\n\n    public function test_can_import_without_extension_with_explicit_reader_type()\n    {\n        $import = new class implements ToArray\n        {\n            /**\n             * @param  array  $array\n             */\n            public function array(array $array)\n            {\n                Assert::assertEquals([\n                    ['test', 'test'],\n                    ['test', 'test'],\n                ], $array);\n            }\n        };\n\n        $this->SUT->import(\n            $import,\n            $this->givenUploadedFile(__DIR__ . '/Data/Disks/Local/import.xlsx', 'import'),\n            null,\n            Excel::XLSX\n        );\n    }\n}\n"
  },
  {
    "path": "tests/HeadingRowImportTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests;\n\nuse Maatwebsite\\Excel\\HeadingRowImport;\nuse Maatwebsite\\Excel\\Imports\\HeadingRowFormatter;\n\nclass HeadingRowImportTest extends TestCase\n{\n    protected function tearDown(): void\n    {\n        HeadingRowFormatter::reset();\n        parent::tearDown();\n    }\n\n    public function test_can_import_only_heading_row()\n    {\n        $import = new HeadingRowImport();\n\n        $headings = $import->toArray('import-users-with-headings.xlsx');\n\n        $this->assertEquals([\n            [\n                ['name', 'email'],\n            ],\n        ], $headings);\n    }\n\n    public function test_can_import_only_heading_row_with_custom_heading_row_formatter()\n    {\n        HeadingRowFormatter::extend('custom', function ($value) {\n            return 'custom-' . $value;\n        });\n\n        HeadingRowFormatter::default('custom');\n\n        $import = new HeadingRowImport();\n\n        $headings = $import->toArray('import-users-with-headings.xlsx');\n\n        $this->assertEquals([\n            [\n                ['custom-name', 'custom-email'],\n            ],\n        ], $headings);\n    }\n\n    public function test_can_import_only_heading_row_with_custom_heading_row_formatter_with_key()\n    {\n        HeadingRowFormatter::extend('custom', function ($value, $key) {\n            return $key;\n        });\n\n        HeadingRowFormatter::default('custom');\n\n        $import = new HeadingRowImport();\n\n        $headings = $import->toArray('import-users-with-headings.xlsx');\n\n        $this->assertEquals([\n            [\n                [0, 1],\n            ],\n        ], $headings);\n    }\n\n    public function test_can_import_only_heading_row_with_custom_row_number()\n    {\n        $import = new HeadingRowImport(2);\n\n        $headings = $import->toArray('import-users-with-headings.xlsx');\n\n        $this->assertEquals([\n            [\n                ['patrick_brouwers', 'patrick_at_maatwebsitenl'],\n            ],\n        ], $headings);\n    }\n\n    public function test_can_import_only_heading_row_for_multiple_sheets()\n    {\n        $import = new HeadingRowImport();\n\n        $headings = $import->toArray('import-multiple-sheets.xlsx');\n\n        $this->assertEquals([\n            [\n                ['1a1', '1b1'], // slugged first row of sheet 1\n            ],\n            [\n                ['2a1', '2b1'], // slugged first row of sheet 2\n            ],\n        ], $headings);\n    }\n\n    public function test_can_import_only_heading_row_for_multiple_sheets_with_key()\n    {\n        HeadingRowFormatter::extend('custom', function ($value, $key) {\n            return $key;\n        });\n\n        HeadingRowFormatter::default('custom');\n        $import = new HeadingRowImport();\n\n        $headings = $import->toArray('import-multiple-sheets.xlsx');\n\n        $this->assertEquals([\n            [\n                [0, 1], // slugged first row of sheet 1\n            ],\n            [\n                [0, 1], // slugged first row of sheet 2\n            ],\n        ], $headings);\n    }\n\n    public function test_can_import_only_heading_row_for_multiple_sheets_with_custom_row_number()\n    {\n        $import = new HeadingRowImport(2);\n\n        $headings = $import->toArray('import-multiple-sheets.xlsx');\n\n        $this->assertEquals([\n            [\n                ['1a2', '1b2'], // slugged 2nd row of sheet 1\n            ],\n            [\n                ['2a2', '2b2'], // slugged 2nd row of sheet 2\n            ],\n        ], $headings);\n    }\n\n    public function test_can_import_heading_row_with_custom_formatter_defined_in_config()\n    {\n        HeadingRowFormatter::extend('custom2', function ($value) {\n            return 'custom2-' . $value;\n        });\n\n        config()->set('excel.imports.heading_row.formatter', 'custom2');\n\n        $import = new HeadingRowImport();\n\n        $headings = $import->toArray('import-users-with-headings.xlsx');\n\n        $this->assertEquals([\n            [\n                ['custom2-name', 'custom2-email'],\n            ],\n        ], $headings);\n    }\n}\n"
  },
  {
    "path": "tests/Helpers/FileHelper.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Helpers;\n\nclass FileHelper\n{\n    public static function absolutePath($fileName, $diskName)\n    {\n        return config('filesystems.disks.' . $diskName . '.root') . DIRECTORY_SEPARATOR . $fileName;\n    }\n\n    public static function recursiveDelete($fileName)\n    {\n        if (is_file($fileName)) {\n            return @unlink($fileName);\n        }\n\n        if (is_dir($fileName)) {\n            $scan = glob(rtrim($fileName, '/') . '/*');\n            foreach ($scan as $path) {\n                self::recursiveDelete($path);\n            }\n\n            return @rmdir($fileName);\n        }\n    }\n}\n"
  },
  {
    "path": "tests/InteractsWithQueueTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests;\n\nuse Illuminate\\Queue\\InteractsWithQueue;\nuse Maatwebsite\\Excel\\Jobs\\AppendDataToSheet;\nuse Maatwebsite\\Excel\\Jobs\\AppendQueryToSheet;\nuse Maatwebsite\\Excel\\Jobs\\AppendViewToSheet;\nuse Maatwebsite\\Excel\\Jobs\\QueueExport;\nuse Maatwebsite\\Excel\\Jobs\\ReadChunk;\n\nclass InteractsWithQueueTest extends TestCase\n{\n    /**\n     * Setup the test environment.\n     */\n    protected function setUp(): void\n    {\n        parent::setUp();\n    }\n\n    public function test_read_chunk_job_can_interact_with_queue()\n    {\n        $this->assertContains(InteractsWithQueue::class, class_uses(ReadChunk::class));\n    }\n\n    public function test_append_data_to_sheet_job_can_interact_with_queue()\n    {\n        $this->assertContains(InteractsWithQueue::class, class_uses(AppendDataToSheet::class));\n    }\n\n    public function test_append_query_to_sheet_job_can_interact_with_queue()\n    {\n        $this->assertContains(InteractsWithQueue::class, class_uses(AppendQueryToSheet::class));\n    }\n\n    public function test_append_view_to_sheet_job_can_interact_with_queue()\n    {\n        $this->assertContains(InteractsWithQueue::class, class_uses(AppendViewToSheet::class));\n    }\n\n    public function test_queue_export_job_can_interact_with_queue()\n    {\n        $this->assertContains(InteractsWithQueue::class, class_uses(QueueExport::class));\n    }\n}\n"
  },
  {
    "path": "tests/Mixins/DownloadCollectionTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Mixins;\n\nuse Illuminate\\Support\\Collection;\nuse Maatwebsite\\Excel\\Excel;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database\\User;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\nuse Symfony\\Component\\HttpFoundation\\BinaryFileResponse;\n\nclass DownloadCollectionTest extends TestCase\n{\n    public function test_can_download_a_collection_as_excel()\n    {\n        $collection = new Collection([\n            ['column_1' => 'test', 'column_2' => 'test'],\n            ['column_1' => 'test2', 'column_2' => 'test2'],\n        ]);\n\n        $response = $collection->downloadExcel('collection-download.xlsx', Excel::XLSX);\n\n        $array = $this->readAsArray($response->getFile()->getPathName(), Excel::XLSX);\n\n        // First row are not headings\n        $firstRow = collect($array)->first();\n        $this->assertEquals(['test', 'test'], $firstRow);\n\n        $this->assertInstanceOf(BinaryFileResponse::class, $response);\n        $this->assertEquals(\n            'attachment; filename=collection-download.xlsx',\n            str_replace('\"', '', $response->headers->get('Content-Disposition'))\n        );\n    }\n\n    public function test_can_download_a_collection_with_headers_as_excel()\n    {\n        $collection = new Collection([\n            ['column_1' => 'test', 'column_2' => 'test'],\n            ['column_1' => 'test', 'column_2' => 'test'],\n        ]);\n\n        $response = $collection->downloadExcel('collection-headers-download.xlsx', Excel::XLSX, true);\n\n        $array = $this->readAsArray($response->getFile()->getPathName(), Excel::XLSX);\n\n        $this->assertEquals(['column_1', 'column_2'], collect($array)->first());\n    }\n\n    public function test_can_download_collection_with_headers_with_hidden_eloquent_attributes()\n    {\n        $collection = new Collection([\n            new User(['name' => 'Patrick', 'password' => 'my_password']),\n        ]);\n\n        $response = $collection->downloadExcel('collection-headers-download.xlsx', Excel::XLSX, true);\n\n        $array = $this->readAsArray($response->getFile()->getPathName(), Excel::XLSX);\n\n        $this->assertEquals(['name'], collect($array)->first());\n    }\n\n    public function test_can_download_collection_with_headers_when_making_attributes_visible()\n    {\n        $user = new User(['name' => 'Patrick', 'password' => 'my_password']);\n        $user->makeVisible(['password']);\n\n        $collection = new Collection([\n            $user,\n        ]);\n\n        $response = $collection->downloadExcel('collection-headers-download.xlsx', Excel::XLSX, true);\n\n        $array = $this->readAsArray($response->getFile()->getPathName(), Excel::XLSX);\n\n        $this->assertEquals(['name', 'password'], collect($array)->first());\n    }\n\n    public function test_can_set_custom_response_headers()\n    {\n        $collection = new Collection([\n            ['column_1' => 'test', 'column_2' => 'test'],\n            ['column_1' => 'test2', 'column_2' => 'test2'],\n        ]);\n\n        $responseHeaders = [\n            'CUSTOMER-HEADER-1' => 'CUSTOMER-HEADER1-VAL',\n            'CUSTOMER-HEADER-2' => 'CUSTOMER-HEADER2-VAL',\n        ];\n        /** @var BinaryFileResponse $response */\n        $response = $collection->downloadExcel('collection-download.xlsx', Excel::XLSX, false, $responseHeaders);\n        $this->assertTrue($response->headers->contains('CUSTOMER-HEADER-1', 'CUSTOMER-HEADER1-VAL'));\n        $this->assertTrue($response->headers->contains('CUSTOMER-HEADER-2', 'CUSTOMER-HEADER2-VAL'));\n    }\n}\n"
  },
  {
    "path": "tests/Mixins/DownloadQueryMacroTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Mixins;\n\nuse Maatwebsite\\Excel\\Excel;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database\\User;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\nuse Symfony\\Component\\HttpFoundation\\BinaryFileResponse;\n\nclass DownloadQueryMacroTest extends TestCase\n{\n    /**\n     * Setup the test environment.\n     */\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $this->loadLaravelMigrations(['--database' => 'testing']);\n        $this->withFactories(__DIR__ . '/../Data/Stubs/Database/Factories');\n\n        factory(User::class)->times(100)->create();\n    }\n\n    public function test_can_download_a_query_as_excel()\n    {\n        $response = User::downloadExcel('query-download.xlsx', Excel::XLSX);\n\n        $array = $this->readAsArray($response->getFile()->getPathName(), Excel::XLSX);\n        $this->assertCount(100, $array);\n\n        $this->assertInstanceOf(BinaryFileResponse::class, $response);\n        $this->assertEquals(\n            'attachment; filename=query-download.xlsx',\n            str_replace('\"', '', $response->headers->get('Content-Disposition'))\n        );\n    }\n\n    public function test_can_download_a_collection_with_headers_as_excel()\n    {\n        $response = User::downloadExcel('collection-headers-download.xlsx', Excel::XLSX, true);\n\n        $array = $this->readAsArray($response->getFile()->getPathName(), Excel::XLSX);\n\n        $this->assertCount(101, $array);\n\n        $this->assertEquals(['id', 'name', 'email', 'remember_token', 'created_at', 'updated_at'], collect($array)->first());\n    }\n}\n"
  },
  {
    "path": "tests/Mixins/ImportAsMacroTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Mixins;\n\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database\\User;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\n\nclass ImportAsMacroTest extends TestCase\n{\n    /**\n     * Setup the test environment.\n     */\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $this->loadLaravelMigrations(['--database' => 'testing']);\n    }\n\n    public function test_can_import_directly_into_a_model_with_mapping()\n    {\n        User::query()->truncate();\n\n        User::importAs('import-users.xlsx', function (array $row) {\n            return [\n                'name'     => $row[0],\n                'email'    => $row[1],\n                'password' => 'secret',\n            ];\n        });\n\n        $this->assertCount(2, User::all());\n        $this->assertEquals([\n            'patrick@maatwebsite.nl',\n            'taylor@laravel.com',\n        ], User::query()->pluck('email')->all());\n    }\n}\n"
  },
  {
    "path": "tests/Mixins/ImportMacroTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Mixins;\n\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database\\User;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\n\nclass ImportMacroTest extends TestCase\n{\n    /**\n     * Setup the test environment.\n     */\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $this->loadLaravelMigrations(['--database' => 'testing']);\n    }\n\n    public function test_can_import_directly_into_a_model()\n    {\n        User::query()->truncate();\n        User::creating(function ($user) {\n            $user->password = 'secret';\n        });\n\n        User::import('import-users-with-headings.xlsx');\n\n        $this->assertCount(2, User::all());\n        $this->assertEquals([\n            'patrick@maatwebsite.nl',\n            'taylor@laravel.com',\n        ], User::query()->pluck('email')->all());\n    }\n}\n"
  },
  {
    "path": "tests/Mixins/StoreCollectionTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Mixins;\n\nuse Illuminate\\Support\\Collection;\nuse Maatwebsite\\Excel\\Excel;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database\\User;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\n\nclass StoreCollectionTest extends TestCase\n{\n    public function test_can_store_a_collection_as_excel()\n    {\n        $collection = new Collection([\n            ['test', 'test'],\n            ['test', 'test'],\n        ]);\n\n        $response = $collection->storeExcel('collection-store.xlsx');\n\n        $this->assertTrue($response);\n        $this->assertFileExists(__DIR__ . '/../Data/Disks/Local/collection-store.xlsx');\n    }\n\n    public function test_can_store_a_collection_as_excel_on_non_default_disk()\n    {\n        $collection = new Collection([\n            ['column_1' => 'test', 'column_2' => 'test'],\n            ['column_1' => 'test2', 'column_2' => 'test2'],\n        ]);\n\n        $response = $collection->storeExcel('collection-store.xlsx', null, Excel::XLSX);\n\n        $file = __DIR__ . '/../Data/Disks/Local/collection-store.xlsx';\n\n        $this->assertTrue($response);\n        $this->assertFileExists($file);\n\n        $array = $this->readAsArray($file, Excel::XLSX);\n\n        // First row are not headings\n        $firstRow = collect($array)->first();\n        $this->assertEquals(['test', 'test'], $firstRow);\n\n        $this->assertEquals([\n            ['test', 'test'],\n            ['test2', 'test2'],\n        ], collect($array)->values()->all());\n    }\n\n    public function test_can_store_a_collection_with_headings_as_excel()\n    {\n        $collection = new Collection([\n            ['column_1' => 'test', 'column_2' => 'test'],\n            ['column_1' => 'test', 'column_2' => 'test'],\n        ]);\n\n        $response = $collection->storeExcel('collection-headers-store.xlsx', null, Excel::XLSX, true);\n\n        $file = __DIR__ . '/../Data/Disks/Local/collection-headers-store.xlsx';\n\n        $this->assertTrue($response);\n        $this->assertFileExists($file);\n\n        $array = $this->readAsArray($file, Excel::XLSX);\n        $this->assertEquals(['column_1', 'column_2'], collect($array)->first());\n\n        $this->assertEquals([\n            ['test', 'test'],\n            ['test', 'test'],\n        ], collect($array)->except(0)->values()->all());\n    }\n\n    public function test_can_store_a_model_collection_with_headings_as_excel()\n    {\n        $this->withFactories(__DIR__ . '/../Data/Stubs/Database/Factories');\n\n        $collection = factory(User::class, 2)->make();\n\n        $response = $collection->storeExcel('model-collection-headers-store.xlsx', null, Excel::XLSX, true);\n\n        $file = __DIR__ . '/../Data/Disks/Local/model-collection-headers-store.xlsx';\n\n        $this->assertTrue($response);\n        $this->assertFileExists($file);\n\n        $array = $this->readAsArray($file, Excel::XLSX);\n        $this->assertEquals(['name', 'email', 'remember_token'], collect($array)->first());\n    }\n}\n"
  },
  {
    "path": "tests/Mixins/StoreQueryMacroTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Mixins;\n\nuse Maatwebsite\\Excel\\Excel;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database\\User;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\n\nclass StoreQueryMacroTest extends TestCase\n{\n    /**\n     * Setup the test environment.\n     */\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $this->loadLaravelMigrations(['--database' => 'testing']);\n        $this->withFactories(__DIR__ . '/../Data/Stubs/Database/Factories');\n\n        factory(User::class)->times(100)->create();\n    }\n\n    public function test_can_download_a_query_as_excel()\n    {\n        $response = User::storeExcel('query-store.xlsx', null, Excel::XLSX);\n\n        $this->assertTrue($response);\n        $this->assertFileExists(__DIR__ . '/../Data/Disks/Local/query-store.xlsx');\n\n        $array = $this->readAsArray(__DIR__ . '/../Data/Disks/Local/query-store.xlsx', Excel::XLSX);\n        $this->assertCount(100, $array);\n    }\n\n    public function test_can_download_a_query_as_excel_on_different_disk()\n    {\n        $response = User::storeExcel('query-store.xlsx', 'test', Excel::XLSX);\n\n        $this->assertTrue($response);\n        $this->assertFileExists(__DIR__ . '/../Data/Disks/Test/query-store.xlsx');\n\n        $array = $this->readAsArray(__DIR__ . '/../Data/Disks/Test/query-store.xlsx', Excel::XLSX);\n        $this->assertCount(100, $array);\n    }\n\n    public function test_can_store_a_query_with_headers_as_excel()\n    {\n        $response = User::storeExcel('query-headers-store.xlsx', null, Excel::XLSX, true);\n\n        $this->assertTrue($response);\n        $this->assertFileExists(__DIR__ . '/../Data/Disks/Local/query-headers-store.xlsx');\n\n        $array = $this->readAsArray(__DIR__ . '/../Data/Disks/Local/query-headers-store.xlsx', Excel::XLSX);\n        $this->assertCount(101, $array);\n    }\n}\n"
  },
  {
    "path": "tests/QueuedExportTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests;\n\nuse Illuminate\\Queue\\Events\\JobProcessing;\nuse Illuminate\\Support\\Facades\\Cache;\nuse Illuminate\\Support\\Facades\\Queue;\nuse Maatwebsite\\Excel\\Excel;\nuse Maatwebsite\\Excel\\Files\\RemoteTemporaryFile;\nuse Maatwebsite\\Excel\\Files\\TemporaryFile;\nuse Maatwebsite\\Excel\\Jobs\\AppendDataToSheet;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\AfterQueueExportJob;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\EloquentCollectionWithMappingExport;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\QueuedExport;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\QueuedExportWithFailedEvents;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\QueuedExportWithFailedHook;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\QueuedExportWithLocalePreferences;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\ShouldQueueExport;\nuse Throwable;\n\nclass QueuedExportTest extends TestCase\n{\n    public function test_can_queue_an_export()\n    {\n        $export = new QueuedExport();\n\n        $export->queue('queued-export.xlsx')->chain([\n            new AfterQueueExportJob(__DIR__ . '/Data/Disks/Local/queued-export.xlsx'),\n        ]);\n    }\n\n    public function test_can_queue_an_export_and_store_on_different_disk()\n    {\n        $export = new QueuedExport();\n\n        $export->queue('queued-export.xlsx', 'test')->chain([\n            new AfterQueueExportJob(__DIR__ . '/Data/Disks/Test/queued-export.xlsx'),\n        ]);\n    }\n\n    public function test_can_queue_export_with_remote_temp_disk()\n    {\n        config()->set('excel.temporary_files.remote_disk', 'test');\n\n        // Delete the local temp file before each append job\n        // to simulate using a shared remote disk, without\n        // having a dependency on a local temp file.\n        $jobs = 0;\n        Queue::before(function (JobProcessing $event) use (&$jobs) {\n            if ($event->job->resolveName() === AppendDataToSheet::class) {\n                /** @var TemporaryFile $tempFile */\n                $tempFile = $this->inspectJobProperty($event->job, 'temporaryFile');\n\n                $this->assertInstanceOf(RemoteTemporaryFile::class, $tempFile);\n\n                // Should exist remote\n                $this->assertTrue(\n                    $tempFile->exists()\n                );\n\n                // File was deleted locally\n                $this->assertFalse(\n                    file_exists($tempFile->getLocalPath())\n                );\n\n                $jobs++;\n            }\n        });\n\n        $export = new QueuedExport();\n\n        $export->queue('queued-export.xlsx')->chain([\n            new AfterQueueExportJob(__DIR__ . '/Data/Disks/Local/queued-export.xlsx'),\n        ]);\n\n        $array = $this->readAsArray(__DIR__ . '/Data/Disks/Local/queued-export.xlsx', Excel::XLSX);\n\n        $this->assertCount(100, $array);\n        $this->assertEquals(3, $jobs);\n    }\n\n    public function test_can_queue_export_with_remote_temp_disk_and_prefix()\n    {\n        config()->set('excel.temporary_files.remote_disk', 'test');\n        config()->set('excel.temporary_files.remote_prefix', 'tmp/');\n\n        $export = new QueuedExport();\n\n        $export->queue('queued-export.xlsx')->chain([\n            new AfterQueueExportJob(__DIR__ . '/Data/Disks/Local/queued-export.xlsx'),\n        ]);\n    }\n\n    public function test_can_implicitly_queue_an_export()\n    {\n        $export = new ShouldQueueExport();\n\n        $export->store('queued-export.xlsx', 'test')->chain([\n            new AfterQueueExportJob(__DIR__ . '/Data/Disks/Test/queued-export.xlsx'),\n        ]);\n    }\n\n    public function test_can_queue_export_with_mapping_on_eloquent_models()\n    {\n        $export = new EloquentCollectionWithMappingExport();\n\n        $export->queue('queued-export.xlsx')->chain([\n            new AfterQueueExportJob(__DIR__ . '/Data/Disks/Local/queued-export.xlsx'),\n        ]);\n\n        $actual = $this->readAsArray(__DIR__ . '/Data/Disks/Local/queued-export.xlsx', 'Xlsx');\n\n        $this->assertEquals([\n            ['Patrick', 'Brouwers'],\n        ], $actual);\n    }\n\n    public function test_can_catch_failures()\n    {\n        $export = new QueuedExportWithFailedHook();\n        try {\n            $export->queue('queued-export.xlsx');\n        } catch (Throwable $e) {\n        }\n\n        $this->assertTrue(app('queue-has-failed'));\n    }\n\n    public function test_can_catch_failures_on_queue_export_job()\n    {\n        $export = new QueuedExportWithFailedEvents();\n\n        try {\n            $export->queue('queued-export.xlsx');\n        } catch (Throwable $e) {\n        }\n\n        $this->assertTrue(app('queue-has-failed-from-queue-export-job'));\n    }\n\n    public function test_can_set_locale_on_queue_export_job()\n    {\n        $currentLocale = app()->getLocale();\n\n        $export = new QueuedExportWithLocalePreferences('ru');\n\n        $export->queue('queued-export.xlsx');\n\n        $this->assertTrue(app('queue-has-correct-locale'));\n\n        $this->assertEquals($currentLocale, app()->getLocale());\n    }\n\n    public function test_can_queue_export_not_flushing_the_cache()\n    {\n        config()->set('excel.cache.driver', 'illuminate');\n\n        Cache::put('test', 'test');\n\n        $export = new QueuedExport();\n\n        $export->queue('queued-export.xlsx')->chain([\n            new AfterQueueExportJob(__DIR__ . '/Data/Disks/Local/queued-export.xlsx'),\n        ]);\n\n        $array = $this->readAsArray(__DIR__ . '/Data/Disks/Local/queued-export.xlsx', Excel::XLSX);\n        $this->assertCount(100, $array);\n\n        $this->assertEquals('test', Cache::get('test'));\n    }\n}\n"
  },
  {
    "path": "tests/QueuedImportTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests;\n\nuse Illuminate\\Foundation\\Bus\\PendingDispatch;\nuse Illuminate\\Queue\\Events\\JobExceptionOccurred;\nuse Illuminate\\Queue\\Events\\JobProcessed;\nuse Illuminate\\Queue\\Events\\JobProcessing;\nuse Illuminate\\Support\\Facades\\Bus;\nuse Illuminate\\Support\\Facades\\Queue;\nuse Maatwebsite\\Excel\\Concerns\\Importable;\nuse Maatwebsite\\Excel\\Files\\RemoteTemporaryFile;\nuse Maatwebsite\\Excel\\Files\\TemporaryFile;\nuse Maatwebsite\\Excel\\Jobs\\AfterImportJob;\nuse Maatwebsite\\Excel\\Jobs\\ReadChunk;\nuse Maatwebsite\\Excel\\SettingsProvider;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\AfterQueueImportJob;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\QueuedImport;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\QueuedImportWithFailure;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\QueuedImportWithMiddleware;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\QueuedImportWithRetryUntil;\nuse Throwable;\n\nclass QueuedImportTest extends TestCase\n{\n    /**\n     * Setup the test environment.\n     */\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $this->loadLaravelMigrations(['--database' => 'testing']);\n        $this->loadMigrationsFrom(__DIR__ . '/Data/Stubs/Database/Migrations');\n    }\n\n    public function test_cannot_queue_import_that_does_not_implement_should_queue()\n    {\n        $this->expectException(\\InvalidArgumentException::class);\n        $this->expectExceptionMessage('Importable should implement ShouldQueue to be queued.');\n\n        $import = new class\n        {\n            use Importable;\n        };\n\n        $import->queue('import-batches.xlsx');\n    }\n\n    public function test_can_queue_an_import()\n    {\n        $import = new QueuedImport();\n\n        $chain = $import->queue('import-batches.xlsx')->chain([\n            new AfterQueueImportJob(5000),\n        ]);\n\n        $this->assertInstanceOf(PendingDispatch::class, $chain);\n    }\n\n    public function test_can_queue_an_import_with_batch_cache_and_file_store()\n    {\n        config()->set('queue.default', 'sync');\n        config()->set('excel.cache.driver', 'batch');\n        config()->set('excel.cache.illuminate.store', 'file');\n        config()->set('excel.cache.batch.memory_limit', 80);\n\n        // Reset the cache settings\n        $this->app->make(SettingsProvider::class)->provide();\n\n        $import = new QueuedImport();\n\n        $chain = $import->queue('import-batches.xlsx');\n\n        $this->assertInstanceOf(PendingDispatch::class, $chain);\n    }\n\n    public function test_can_queue_import_with_remote_temp_disk()\n    {\n        config()->set('excel.temporary_files.remote_disk', 'test');\n\n        // Delete the local temp file before each read chunk job\n        // to simulate using a shared remote disk, without\n        // having a dependency on a local temp file.\n        Queue::before(function (JobProcessing $event) {\n            if ($event->job->resolveName() === ReadChunk::class) {\n                /** @var TemporaryFile $tempFile */\n                $tempFile = $this->inspectJobProperty($event->job, 'temporaryFile');\n\n                $this->assertInstanceOf(RemoteTemporaryFile::class, $tempFile);\n\n                // Should exist remote\n                $this->assertTrue(\n                    $tempFile->exists()\n                );\n\n                $this->assertTrue(\n                    unlink($tempFile->getLocalPath())\n                );\n            }\n        });\n\n        $import = new QueuedImport();\n\n        $chain = $import->queue('import-batches.xlsx')->chain([\n            new AfterQueueImportJob(5000),\n        ]);\n\n        $this->assertInstanceOf(PendingDispatch::class, $chain);\n    }\n\n    public function test_can_keep_extension_for_temp_file_on_remote_disk()\n    {\n        config()->set('excel.temporary_files.remote_disk', 'test');\n\n        Queue::before(function (JobProcessing $event) {\n            if ($event->job->resolveName() === ReadChunk::class) {\n                /** @var TemporaryFile $tempFile */\n                $tempFile = $this->inspectJobProperty($event->job, 'temporaryFile');\n\n                $this->assertStringContains('.xlsx', $tempFile->getLocalPath());\n            }\n        });\n        (new QueuedImport())->queue('import-batches.xlsx');\n    }\n\n    public function test_can_queue_import_with_remote_temp_disk_and_prefix()\n    {\n        config()->set('excel.temporary_files.remote_disk', 'test');\n        config()->set('excel.temporary_files.remote_prefix', 'tmp/');\n\n        $import = new QueuedImport();\n\n        $chain = $import->queue('import-batches.xlsx')->chain([\n            new AfterQueueImportJob(5000),\n        ]);\n\n        $this->assertInstanceOf(PendingDispatch::class, $chain);\n    }\n\n    public function test_can_automatically_delete_temp_file_on_failure_when_using_remote_disk()\n    {\n        config()->set('excel.temporary_files.remote_disk', 'test');\n        $tempFile = '';\n\n        Queue::exceptionOccurred(function (JobExceptionOccurred $event) use (&$tempFile) {\n            if ($event->job->resolveName() === ReadChunk::class) {\n                $tempFile = $this->inspectJobProperty($event->job, 'temporaryFile');\n            }\n        });\n\n        try {\n            (new QueuedImportWithFailure())->queue('import-batches.xlsx');\n        } catch (Throwable $e) {\n            $this->assertEquals('Something went wrong in the chunk', $e->getMessage());\n        }\n\n        $this->assertFalse($tempFile->existsLocally());\n        $this->assertTrue($tempFile->exists());\n    }\n\n    public function test_cannot_automatically_delete_temp_file_on_failure_when_using_local_disk()\n    {\n        $tempFile = '';\n\n        Queue::exceptionOccurred(function (JobExceptionOccurred $event) use (&$tempFile) {\n            if ($event->job->resolveName() === ReadChunk::class) {\n                $tempFile = $this->inspectJobProperty($event->job, 'temporaryFile');\n            }\n        });\n\n        try {\n            (new QueuedImportWithFailure())->queue('import-batches.xlsx');\n        } catch (Throwable $e) {\n            $this->assertEquals('Something went wrong in the chunk', $e->getMessage());\n        }\n\n        $this->assertTrue($tempFile->exists());\n    }\n\n    public function test_can_force_remote_download_and_deletion_for_each_chunk_on_queue()\n    {\n        config()->set('excel.temporary_files.remote_disk', 'test');\n        config()->set('excel.temporary_files.force_resync_remote', true);\n        Bus::fake([AfterImportJob::class]);\n\n        Queue::after(function (JobProcessed $event) {\n            if ($event->job->resolveName() === ReadChunk::class) {\n                $tempFile = $this->inspectJobProperty($event->job, 'temporaryFile');\n\n                // Should not exist locally after each chunk\n                $this->assertFalse(\n                    $tempFile->existsLocally()\n                );\n            }\n        });\n\n        (new QueuedImport())->queue('import-batches.xlsx');\n    }\n\n    public function test_can_define_middleware_method_on_queued_import()\n    {\n        try {\n            (new QueuedImportWithMiddleware())->queue('import-batches.xlsx');\n        } catch (Throwable $e) {\n            $this->assertEquals('Job reached middleware method', $e->getMessage());\n        }\n    }\n\n    public function test_can_define_retry_until_method_on_queued_import()\n    {\n        try {\n            (new QueuedImportWithRetryUntil())->queue('import-batches.xlsx');\n        } catch (Throwable $e) {\n            $this->assertEquals('Job reached retryUntil method', $e->getMessage());\n        }\n    }\n\n    public function test_can_define_max_exceptions_property_on_queued_import()\n    {\n        $maxExceptionsCount = 0;\n\n        Queue::exceptionOccurred(function (JobExceptionOccurred $event) use (&$maxExceptionsCount) {\n            if ($event->job->resolveName() === ReadChunk::class) {\n                $maxExceptionsCount = $this->inspectJobProperty($event->job, 'maxExceptions');\n            }\n        });\n\n        try {\n            $import                = new QueuedImportWithFailure();\n            $import->maxExceptions = 3;\n            $import->queue('import-batches.xlsx');\n        } catch (Throwable $e) {\n            $this->assertEquals('Something went wrong in the chunk', $e->getMessage());\n        }\n\n        $this->assertEquals(3, $maxExceptionsCount);\n    }\n}\n"
  },
  {
    "path": "tests/QueuedQueryExportTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests;\n\nuse Maatwebsite\\Excel\\SettingsProvider;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\AfterQueueExportJob;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database\\User;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\FromUsersQueryExport;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\FromUsersQueryExportWithMapping;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\FromUsersScoutExport;\n\nclass QueuedQueryExportTest extends TestCase\n{\n    /**\n     * Setup the test environment.\n     */\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $this->loadLaravelMigrations(['--database' => 'testing']);\n        $this->withFactories(__DIR__ . '/Data/Stubs/Database/Factories');\n\n        factory(User::class)->times(100)->create([]);\n    }\n\n    public function test_can_queue_an_export()\n    {\n        $export = new FromUsersQueryExport();\n\n        $export->queue('queued-query-export.xlsx')->chain([\n            new AfterQueueExportJob(__DIR__ . '/Data/Disks/Local/queued-query-export.xlsx'),\n        ]);\n\n        $actual = $this->readAsArray(__DIR__ . '/Data/Disks/Local/queued-query-export.xlsx', 'Xlsx');\n\n        $this->assertCount(100, $actual);\n\n        // 6 of the 7 columns in export, excluding the \"hidden\" password column.\n        $this->assertCount(6, $actual[0]);\n    }\n\n    public function test_can_queue_an_export_with_batch_cache_and_file_store()\n    {\n        config()->set('queue.default', 'sync');\n        config()->set('excel.cache.driver', 'batch');\n        config()->set('excel.cache.illuminate.store', 'file');\n        config()->set('excel.cache.batch.memory_limit', 80);\n\n        // Reset the cache settings\n        $this->app->make(SettingsProvider::class)->provide();\n\n        $export = new FromUsersQueryExport();\n\n        $export->queue('queued-query-export.xlsx')->chain([\n            new AfterQueueExportJob(__DIR__ . '/Data/Disks/Local/queued-query-export.xlsx'),\n        ]);\n\n        $actual = $this->readAsArray(__DIR__ . '/Data/Disks/Local/queued-query-export.xlsx', 'Xlsx');\n\n        $this->assertCount(100, $actual);\n    }\n\n    public function test_can_queue_an_export_with_mapping()\n    {\n        $export = new FromUsersQueryExportWithMapping();\n\n        $export->queue('queued-query-export-with-mapping.xlsx')->chain([\n            new AfterQueueExportJob(__DIR__ . '/Data/Disks/Local/queued-query-export-with-mapping.xlsx'),\n        ]);\n\n        $actual = $this->readAsArray(__DIR__ . '/Data/Disks/Local/queued-query-export-with-mapping.xlsx', 'Xlsx');\n\n        $this->assertCount(100, $actual);\n\n        // Only 1 column when using map()\n        $this->assertCount(1, $actual[0]);\n        $this->assertEquals(User::value('name'), $actual[0][0]);\n    }\n\n    public function test_can_queue_scout_export()\n    {\n        if (!class_exists('\\Laravel\\Scout\\Engines\\DatabaseEngine')) {\n            $this->markTestSkipped('Laravel Scout is too old');\n\n            return;\n        }\n\n        $export = new FromUsersScoutExport();\n\n        $export->queue('queued-scout-export.xlsx')->chain([\n            new AfterQueueExportJob(__DIR__ . '/Data/Disks/Local/queued-scout-export.xlsx'),\n        ]);\n\n        $actual = $this->readAsArray(__DIR__ . '/Data/Disks/Local/queued-scout-export.xlsx', 'Xlsx');\n\n        $this->assertCount(100, $actual);\n\n        // 6 of the 7 columns in export, excluding the \"hidden\" password column.\n        $this->assertCount(6, $actual[0]);\n    }\n}\n"
  },
  {
    "path": "tests/QueuedViewExportTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests;\n\nuse Illuminate\\Support\\Collection;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\AfterQueueExportJob;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\Database\\User;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\FromViewExportWithMultipleSheets;\nuse Maatwebsite\\Excel\\Tests\\Data\\Stubs\\SheetForUsersFromView;\n\nclass QueuedViewExportTest extends TestCase\n{\n    /**\n     * Setup the test environment.\n     */\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $this->loadLaravelMigrations(['--database' => 'testing']);\n        $this->withFactories(__DIR__ . '/Data/Stubs/Database/Factories');\n    }\n\n    public function test_can_queue_an_export()\n    {\n        $users  = factory(User::class)->times(100)->create([]);\n        $export = new SheetForUsersFromView($users);\n\n        $export->queue('queued-view-export.xlsx')->chain([\n            new AfterQueueExportJob(__DIR__ . '/Data/Disks/Local/queued-view-export.xlsx'),\n        ]);\n\n        $actual = $this->readAsArray(__DIR__ . '/Data/Disks/Local/queued-view-export.xlsx', 'Xlsx');\n\n        $this->assertCount(101, $actual);\n    }\n\n    public function test_can_export_multiple_sheets_from_view()\n    {\n        /** @var Collection|User[] $users */\n        $users = factory(User::class)->times(300)->make();\n\n        $export = new FromViewExportWithMultipleSheets($users);\n\n        $export->queue('queued-multiple-view-export.xlsx')->chain([\n            new AfterQueueExportJob(__DIR__ . '/Data/Disks/Local/queued-multiple-view-export.xlsx'),\n        ]);\n\n        $contents = $this->readAsArray(__DIR__ . '/Data/Disks/Local/queued-multiple-view-export.xlsx', 'Xlsx', 0);\n\n        $expected = $users->forPage(1, 100)->map(function (User $user) {\n            return [\n                $user->name,\n                $user->email,\n            ];\n        })->prepend(['Name', 'Email'])->toArray();\n\n        $this->assertEquals(101, sizeof($contents));\n        $this->assertEquals($expected, $contents);\n\n        $contents = $this->readAsArray(__DIR__ . '/Data/Disks/Local/queued-multiple-view-export.xlsx', 'Xlsx', 2);\n\n        $expected = $users->forPage(3, 100)->map(function (User $user) {\n            return [\n                $user->name,\n                $user->email,\n            ];\n        })->prepend(['Name', 'Email'])->toArray();\n\n        $this->assertEquals(101, sizeof($contents));\n        $this->assertEquals($expected, $contents);\n    }\n}\n"
  },
  {
    "path": "tests/TemporaryFileTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests;\n\nuse Maatwebsite\\Excel\\Files\\TemporaryFileFactory;\nuse Maatwebsite\\Excel\\Tests\\Helpers\\FileHelper;\n\nclass TemporaryFileTest extends TestCase\n{\n    private $defaultDirectoryPermissions;\n    private $defaultFilePermissions;\n\n    /**\n     * Setup the test environment.\n     */\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $path = FileHelper::absolutePath('rights-test-permissions', 'local');\n        mkdir($path);\n        $this->defaultDirectoryPermissions = substr(sprintf('%o', fileperms($path)), -4);\n\n        $filePath = $path . DIRECTORY_SEPARATOR . 'file-permissions';\n        touch($filePath);\n        $this->defaultFilePermissions = substr(sprintf('%o', fileperms($filePath)), -4);\n\n        @unlink($filePath);\n        @rmdir($path);\n    }\n\n    public function test_can_use_default_rights()\n    {\n        $path = FileHelper::absolutePath('rights-test', 'local');\n        FileHelper::recursiveDelete($path);\n\n        config()->set('excel.temporary_files.local_path', $path);\n\n        $temporaryFileFactory = app(TemporaryFileFactory::class);\n\n        $temporaryFile = $temporaryFileFactory->makeLocal(null, 'txt');\n        $temporaryFile->put('data-set');\n\n        $this->assertFileExists($temporaryFile->getLocalPath());\n        $this->assertEquals($this->defaultDirectoryPermissions, substr(sprintf('%o', fileperms(dirname($temporaryFile->getLocalPath()))), -4));\n        $this->assertEquals($this->defaultFilePermissions, substr(sprintf('%o', fileperms($temporaryFile->getLocalPath())), -4));\n    }\n\n    public function test_can_use_dir_rights()\n    {\n        $path = FileHelper::absolutePath('rights-test', 'local');\n        FileHelper::recursiveDelete($path);\n\n        config()->set('excel.temporary_files.local_path', $path);\n        config()->set('excel.temporary_files.local_permissions.dir', 0700);\n\n        $temporaryFileFactory = app(TemporaryFileFactory::class);\n\n        $temporaryFile = $temporaryFileFactory->makeLocal(null, 'txt');\n        $temporaryFile->put('data-set');\n\n        $this->assertFileExists($temporaryFile->getLocalPath());\n        $this->assertEquals('0700', substr(sprintf('%o', fileperms(dirname($temporaryFile->getLocalPath()))), -4));\n        $this->assertEquals($this->defaultFilePermissions, substr(sprintf('%o', fileperms($temporaryFile->getLocalPath())), -4));\n    }\n\n    public function test_can_use_file_rights()\n    {\n        $path = FileHelper::absolutePath('rights-test', 'local');\n        FileHelper::recursiveDelete($path);\n\n        config()->set('excel.temporary_files.local_path', $path);\n        config()->set('excel.temporary_files.local_permissions.file', 0600);\n\n        $temporaryFileFactory = app(TemporaryFileFactory::class);\n\n        $temporaryFile = $temporaryFileFactory->makeLocal(null, 'txt');\n        $temporaryFile->put('data-set');\n\n        $this->assertFileExists($temporaryFile->getLocalPath());\n        $this->assertEquals($this->defaultDirectoryPermissions, substr(sprintf('%o', fileperms(dirname($temporaryFile->getLocalPath()))), -4));\n        $this->assertEquals('0600', substr(sprintf('%o', fileperms($temporaryFile->getLocalPath())), -4));\n    }\n}\n"
  },
  {
    "path": "tests/TestCase.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests;\n\nuse Illuminate\\Contracts\\Queue\\Job;\nuse Illuminate\\Http\\Testing\\File;\nuse Maatwebsite\\Excel\\ExcelServiceProvider;\nuse Orchestra\\Testbench\\TestCase as OrchestraTestCase;\nuse PhpOffice\\PhpSpreadsheet\\IOFactory;\nuse PHPUnit\\Framework\\Constraint\\StringContains;\n\nclass TestCase extends OrchestraTestCase\n{\n    /**\n     * @param  string  $filePath\n     * @param  string  $writerType\n     * @return \\PhpOffice\\PhpSpreadsheet\\Spreadsheet\n     *\n     * @throws \\PhpOffice\\PhpSpreadsheet\\Reader\\Exception\n     */\n    public function read(string $filePath, string $writerType)\n    {\n        $reader = IOFactory::createReader($writerType);\n\n        return $reader->load($filePath);\n    }\n\n    /**\n     * @param  string  $filePath\n     * @param  string|null  $filename\n     * @return File\n     */\n    public function givenUploadedFile(string $filePath, ?string $filename = null): File\n    {\n        $filename = $filename ?? basename($filePath);\n\n        // Create temporary file.\n        $newFilePath = tempnam(sys_get_temp_dir(), 'import-');\n\n        // Copy the existing file to a temporary file.\n        copy($filePath, $newFilePath);\n\n        return new File($filename, fopen($newFilePath, 'r'));\n    }\n\n    /**\n     * @param  string  $filePath\n     * @param  string  $writerType\n     * @param  int|null  $sheetIndex\n     * @return array\n     *\n     * @throws \\PhpOffice\\PhpSpreadsheet\\Exception\n     */\n    protected function readAsArray(string $filePath, string $writerType, ?int $sheetIndex = null)\n    {\n        $spreadsheet = $this->read($filePath, $writerType);\n\n        if (null === $sheetIndex) {\n            $sheet = $spreadsheet->getActiveSheet();\n        } else {\n            $sheet = $spreadsheet->getSheet($sheetIndex);\n        }\n\n        return $sheet->toArray();\n    }\n\n    /**\n     * @param  \\Illuminate\\Foundation\\Application  $app\n     * @return array\n     */\n    protected function getPackageProviders($app)\n    {\n        return [\n            ExcelServiceProvider::class,\n        ];\n    }\n\n    /**\n     * @param  \\Illuminate\\Foundation\\Application  $app\n     */\n    protected function getEnvironmentSetUp($app)\n    {\n        $app['config']->set('filesystems.disks.local.root', __DIR__ . '/Data/Disks/Local');\n        $app['config']->set('filesystems.disks.test', [\n            'driver' => 'local',\n            'root'   => __DIR__ . '/Data/Disks/Test',\n        ]);\n\n        $app['config']->set('database.default', 'testing');\n        $app['config']->set('database.connections.testing', [\n            'driver'   => 'mysql',\n            'host'     => env('DB_HOST'),\n            'port'     => env('DB_PORT'),\n            'database' => env('DB_DATABASE'),\n            'username' => env('DB_USERNAME'),\n            'password' => env('DB_PASSWORD'),\n        ]);\n\n        $app['config']->set('view.paths', [\n            __DIR__ . '/Data/Stubs/Views',\n        ]);\n    }\n\n    /**\n     * @param  Job  $job\n     * @param  string  $property\n     * @return mixed\n     */\n    protected function inspectJobProperty(Job $job, string $property)\n    {\n        $dict  = (array) unserialize($job->payload()['data']['command']);\n        $class = $job->resolveName();\n\n        return $dict[$property] ?? $dict[\"\\0*\\0$property\"] ?? $dict[\"\\0$class\\0$property\"];\n    }\n\n    /**\n     * @param  string  $needle\n     * @param  string  $haystack\n     * @param  string  $message\n     */\n    protected function assertStringContains(string $needle, string $haystack, string $message = '')\n    {\n        if (method_exists($this, 'assertStringContainsString')) {\n            $this->assertStringContainsString($needle, $haystack, $message);\n        } else {\n            static::assertThat($haystack, new StringContains($needle, false), $message);\n        }\n    }\n\n    /**\n     * @param  string  $path\n     */\n    protected function assertFileMissing(string $path)\n    {\n        if (method_exists($this, 'assertFileDoesNotExist')) {\n            $this->assertFileDoesNotExist($path);\n        } else {\n            $this->assertFileNotExists($path);\n        }\n    }\n\n    protected function assertRegex(string $pattern, string $string)\n    {\n        if (method_exists($this, 'assertMatchesRegularExpression')) {\n            $this->assertMatchesRegularExpression($pattern, $string);\n        } else {\n            $this->assertRegExp($pattern, $string);\n        }\n    }\n}\n"
  },
  {
    "path": "tests/Validators/RowValidatorTest.php",
    "content": "<?php\n\nnamespace Maatwebsite\\Excel\\Tests\\Validators;\n\nuse Illuminate\\Contracts\\Validation\\Factory;\nuse Maatwebsite\\Excel\\Tests\\TestCase;\nuse Maatwebsite\\Excel\\Validators\\RowValidator;\n\nclass RowValidatorTest extends TestCase\n{\n    /**\n     * The RowValidator instance.\n     */\n    protected $validator;\n\n    /**\n     * Set up the test.\n     */\n    public function setUp(): void\n    {\n        parent::setUp();\n\n        $this->validator = new RowValidator(app(Factory::class));\n    }\n\n    public function test_format_rule_with_array_input()\n    {\n        $rules = ['rule1', 'rule2'];\n\n        $result = $this->callPrivateMethod('formatRule', [$rules]);\n\n        $this->assertEquals($rules, $result);\n    }\n\n    public function test_format_rule_with_object_input()\n    {\n        $rule = new \\stdClass();\n\n        $result = $this->callPrivateMethod('formatRule', [$rule]);\n\n        $this->assertEquals($rule, $result);\n    }\n\n    public function test_format_rule_with_callable_input()\n    {\n        $rule = function () {\n            return 'callable';\n        };\n\n        $result = $this->callPrivateMethod('formatRule', [$rule]);\n\n        $this->assertEquals($rule, $result);\n    }\n\n    public function test_format_rule_with_required_without_all()\n    {\n        $rule = 'required_without_all:first_name,last_name';\n\n        $result = $this->callPrivateMethod('formatRule', [$rule]);\n\n        $this->assertEquals('required_without_all:*.first_name,*.last_name', $result);\n    }\n\n    public function test_format_rule_with_required_without()\n    {\n        $rule = 'required_without:first_name';\n\n        $result = $this->callPrivateMethod('formatRule', [$rule]);\n\n        $this->assertEquals('required_without:*.first_name', $result);\n    }\n\n    public function test_format_rule_with_string_input_not_matching_pattern()\n    {\n        $rule = 'rule';\n\n        $result = $this->callPrivateMethod('formatRule', [$rule]);\n\n        $this->assertEquals($rule, $result);\n    }\n\n    /**\n     * Call a private function.\n     *\n     * @param  string  $name\n     * @param  array  $args\n     * @return mixed\n     */\n    public function callPrivateMethod(string $name, array $args)\n    {\n        $method = new \\ReflectionMethod(RowValidator::class, $name);\n        $method->setAccessible(true);\n\n        return $method->invokeArgs($this->validator, $args);\n    }\n}\n"
  }
]