[
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*]\ncharset = utf-8\nend_of_line = lf\ninsert_final_newline = true\nindent_style = space\nindent_size = 4\ntrim_trailing_whitespace = true\n\n[*.md]\ntrim_trailing_whitespace = false\n\n[*.{yml,yaml}]\nindent_size = 2"
  },
  {
    "path": ".gitattributes",
    "content": "* text=auto\n\n/.github export-ignore\n/tests export-ignore\n.editorconfig export-ignore\n.gitattributes export-ignore\n.gitignore export-ignore\n.styleci.yml export-ignore\nCHANGELOG-* export-ignore\nCODE_OF_CONDUCT.md export-ignore\nCONTRIBUTING.md export-ignore\nphpunit.xml export-ignore\n"
  },
  {
    "path": ".github/CODE_OF_CONDUCT.md",
    "content": "# Contributor Code of Conduct\n\nAs contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.\n\nWe are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, age, or religion.\n\nExamples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.\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. Project maintainers who do not follow the Code of Conduct may be removed from the project team.\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.\n\nThis Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "# These are supported funding model platforms\n\n# github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]\ngithub: [codedredd]\n#open_collective: codedredd\n#custom:\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "content": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: ''\nassignees: ''\n---\n\n### Reproduction\n\nIf possible, provide a boiled down editable reproduction using a service like JSFiddle, Codepen, CodeSandbox, or a GitHub repository based on this template: https://github.com/piniajs/bug-report. A failing unit test is even better! Otherwise provide as much information as possible to reproduce the problem. You can find examples of different environments at https://github.com/piniajs?q=example&type=source and use them as a bug reproduction.\nIf no reproduction is provided and the information is not enough to reproduce the problem, we won't be able to give it a look **and the issue will be converted into a question and moved to discussions**.\n\n### Steps to reproduce the behavior\n\n1. Go to '...'\n2. Click on '....'\n3. Scroll down to '....'\n4. See error\n\n### Expected behavior\n\nA clear and concise description of what you expected to happen.\n\n### Actual behavior\n\nA clear and concise description of what actually happens.\n\n### Additional information\n\nAdd any other context about the problem here.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "blank_issues_enabled: false\ncontact_links:\n  - name: Ask a question\n    url: https://github.com/CodeDredd/laravel-soap/discussions/new?category=q-a\n    about: Ask the community for help\n  - name: Request a feature\n    url: https://github.com/CodeDredd/laravel-soap/discussions/new?category=ideas\n    about: Share ideas for new features\n  - name: Report a security issue\n    url: https://github.com/CodeDredd/laravel-soap/security/policy\n    about: Learn how to notify us for sensitive bugs\n  - name: Report a bug\n    url: https://github.com/CodeDredd/laravel-soap/issues/new\n    about: Report a reproducable bug\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "content": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: ''\nlabels: feature request\nassignees: ''\n\n---\n\n### What problem is this solving\n\nA clear and concise description of what the problem is. Ex. when using the function X we cannot do Y.\n\n### Proposed solution\n\nA clear and concise description of what you want to happen with an API proposal when applicable\n\n### Describe alternatives you've considered\n\nA clear and concise description of any alternative solutions or features you've considered.\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "Issue:\n\n## What I did\n\n## How to test\n\n- Does this need an update to the documentation?\n\nIf your answer is yes to any of these, please make sure to include it in your PR.\n\n<!--\n\nMaintainers: Please tag your pull request with at least one of the following:\n`[\"cleanup\", \"BREAKING CHANGE\", \"feature\", \"bug\", \"documentation\", \"maintenance\"]`\n\n-->\n"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "# Please see the documentation for all configuration options:\n# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates\n\nversion: 2\nupdates:\n\n  - package-ecosystem: \"github-actions\"\n    directory: \"/\"\n    schedule:\n      interval: \"weekly\"\n    labels:\n      - \"dependencies\"\n"
  },
  {
    "path": ".github/pr-labeler.yml",
    "content": "feature: ['feature/*', 'feat/*']\nfix: fix/*\nchore: chore/*"
  },
  {
    "path": ".github/release-drafter.yml",
    "content": "name-template: 'v$NEXT_PATCH_VERSION'\ntag-template: 'v$NEXT_PATCH_VERSION'\ncategories:\n  - title: '🚀 Features'\n    labels:\n      - 'feature'\n      - 'enhancement'\n  - title: '🐛 Bug Fixes'\n    labels:\n      - 'fix'\n      - 'bugfix'\n      - 'bug'\n  - title: '🧰 Maintenance'\n    labels:\n      - 'chore'\n      - 'documentation'\n      - 'dependencies'\n  - title: ':boom: BREAKING CHANGE'\n    label: 'BREAKING CHANGE'\nchange-template: '- $TITLE @$AUTHOR (#$NUMBER)'\ntemplate: |\n  ## Changes\n\n  $CHANGES\n"
  },
  {
    "path": ".github/stale.yml",
    "content": "# Number of days of inactivity before an issue becomes stale\ndaysUntilStale: 21\n# Number of days of inactivity before a stale issue is closed\ndaysUntilClose: 60\n# Issues with these labels will never be considered stale\nexemptLabels:\n  - todo\n  - 'in progress'\n# Label to use when marking an issue as stale\nstaleLabel: inactive\n# Comment to post when marking an issue as stale. Set to `false` to disable\nmarkComment: >\n  Hi everyone! Seems like there hasn't been much going on in this issue lately.\n  If there are still questions, comments, or bugs, please feel free to continue\n  the discussion. Unfortunately, we don't have time to get to every issue. We\n  are always open to contributions so please send us a pull request if you would\n  like to help. Inactive issues will be closed after 30 days. Thanks!\n# Comment to post when closing a stale issue. Set to `false` to disable\ncloseComment: >\n  Hey there, it's me again! I am going close this issue to help our maintainers\n  focus on the current development roadmap instead. If the issue mentioned is\n  still a concern, please open a new ticket and mention this old one. Cheers\n  and thanks for using Laravel Soap!\n"
  },
  {
    "path": ".github/workflows/dependabot-auto-merge.yml",
    "content": "\nname: dependabot-auto-merge\non: pull_request_target\n\npermissions:\n  pull-requests: write\n  contents: write\n\njobs:\n  dependabot:\n    runs-on: ubuntu-latest\n    if: ${{ github.actor == 'dependabot[bot]' }}\n    steps:\n\n      - name: Dependabot metadata\n        id: metadata\n        uses: dependabot/fetch-metadata@v1.6.0\n        with:\n          github-token: \"${{ secrets.GITHUB_TOKEN }}\"\n\n      - name: Auto-merge Dependabot PRs for semver-minor updates\n        if: ${{steps.metadata.outputs.update-type == 'version-update:semver-minor'}}\n        run: gh pr merge --auto --merge \"$PR_URL\"\n        env:\n          PR_URL: ${{github.event.pull_request.html_url}}\n          GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}\n\n      - name: Auto-merge Dependabot PRs for semver-patch updates\n        if: ${{steps.metadata.outputs.update-type == 'version-update:semver-patch'}}\n        run: gh pr merge --auto --merge \"$PR_URL\"\n        env:\n          PR_URL: ${{github.event.pull_request.html_url}}\n          GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}\n"
  },
  {
    "path": ".github/workflows/mkdocs.yml",
    "content": "name: documentation\non:\n  push:\n    branches:\n      - master\n\njobs:\n  build:\n    name: Deploy docs\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout master\n        uses: actions/checkout@v3\n\n      - name: Deploy docs\n        uses: mhausenblas/mkdocs-deploy-gh-pages@master\n        env:\n          PERSONAL_TOKEN: ${{ secrets.PERSONAL_TOKEN }}\n"
  },
  {
    "path": ".github/workflows/php-cs-fixer.yml",
    "content": "name: Check & fix styling\n\non: [push]\n\njobs:\n  php-cs-fixer:\n    runs-on: ubuntu-latest\n\n    steps:\n      - name: Checkout code\n        uses: actions/checkout@v3\n        with:\n          ref: ${{ github.head_ref }}\n\n      - name: Run PHP CS Fixer\n        uses: docker://oskarstark/php-cs-fixer-ga\n        with:\n          args: --config=.php_cs.dist.php --allow-risky=yes\n\n#      - name: Commit changes\n#        uses: stefanzweifel/git-auto-commit-action@v4\n#        with:\n#          commit_message: Fix styling\n"
  },
  {
    "path": ".github/workflows/phpstan.yml",
    "content": "name: PHPStan\n\non:\n  push:\n    paths:\n      - '**.php'\n      - 'phpstan.neon'\n\njobs:\n  phpstan:\n    name: phpstan\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v3\n\n      - name: Setup PHP\n        uses: shivammathur/setup-php@v2\n        with:\n          php-version: '8.2'\n          coverage: none\n\n      - name: Install composer dependencies\n        uses: ramsey/composer-install@v2\n\n      - name: Run PHPStan\n        run: ./vendor/bin/phpstan --error-format=github\n"
  },
  {
    "path": ".github/workflows/pr-labeler.yml",
    "content": "name: PR Labeler\non:\n  pull_request:\n    types: [opened]\n\njobs:\n  pr-labeler:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: TimonVS/pr-labeler-action@v4\n        with:\n          configuration-path: .github/pr-labeler.yml # optional, .github/pr-labeler.yml is the default value\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}"
  },
  {
    "path": ".github/workflows/releaseDrafter.yml",
    "content": "name: Release Drafter\n\non:\n  push:\n    # branches to consider in the event; optional, defaults to all\n    branches:\n      - master\n      - '1.0'\n\njobs:\n  update_release_draft:\n    runs-on: ubuntu-latest\n    steps:\n      # Drafts your next Release notes as Pull Requests are merged into \"master\"\n      - uses: release-drafter/release-drafter@v5.25.0\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n"
  },
  {
    "path": ".github/workflows/tests.yml",
    "content": "name: Unit Tests\n\non: push\n\nenv:\n  # see https://github.com/composer/composer/issues/9368#issuecomment-718112361\n  COMPOSER_ROOT_VERSION: \"dev-master\"\n\njobs:\n  provide_php_versions_json:\n    runs-on: ubuntu-latest\n\n    steps:\n      # git clone + use PHP + composer install\n      -   uses: actions/checkout@v3\n      -   uses: shivammathur/setup-php@v2\n          with:\n            php-version: 8.2\n            tools: composer:v2\n\n      -   run: composer install --no-progress --ansi\n\n      -\n        # to see the output\n        run: vendor/bin/easy-ci php-versions-json\n\n      # here we create the json, we need the \"id:\" so we can use it in \"outputs\" bellow\n\n      -\n        id: output_data\n        run: echo \"::set-output name=matrix::$(vendor/bin/easy-ci php-versions-json)\"\n\n    # here, we save the result of this 1st phase to the \"outputs\"\n    outputs:\n      matrix: ${{ steps.output_data.outputs.matrix }}\n\n  unit_tests:\n    needs: provide_php_versions_json\n\n    runs-on: ubuntu-latest\n\n    strategy:\n      fail-fast: false\n      matrix:\n        php: ${{ fromJson(needs.provide_php_versions_json.outputs.matrix) }}\n\n    name: PHP ${{ matrix.php }} tests\n\n    steps:\n      -   uses: actions/checkout@v3\n      # required for \"git tag\" presence for changelog-linker git tags resolver; default is 1\n      # https://github.com/actions/checkout#fetch-all-tags\n      -   run: git fetch --depth=1 origin +refs/tags/*:refs/tags/*\n\n      # see https://github.com/shivammathur/setup-php\n      -   uses: shivammathur/setup-php@v2\n          with:\n            php-version: ${{ matrix.php }}\n            extensions: mbstring, intl\n            ini-values: post_max_size=256M, max_execution_time=180\n            coverage: xdebug\n            tools: php-cs-fixer, phpunit, composer:v2\n\n      # composer install cache - https://github.com/ramsey/composer-install\n      -\n        if: \"matrix.php == 7.3\"\n        run: composer update  --no-progress --ansi --prefer-lowest\n\n      -\n        if: \"matrix.php == 7.4\"\n        uses: \"ramsey/composer-install@v2\"\n\n      -\n        if: \"matrix.php >= 8\"\n        uses: \"ramsey/composer-install@v2\"\n        with:\n          composer-options: \"--ignore-platform-req php\"\n\n      -\n        run: vendor/bin/phpunit\n"
  },
  {
    "path": ".gitignore",
    "content": ".idea\n.env\n.php_cs\n.php_cs.cache\n.phpunit.result.cache\nbuild\ncomposer.lock\ncoverage\ndocs\nphpunit.xml\nphpstan.neon\ntestbench.yaml\nvendor\n.php-cs-fixer.cache\nray.php\n/docs/v3/node_modules/\n/.phpunit.cache\n"
  },
  {
    "path": ".mailmap",
    "content": "CodeDredd <gregor@codedredd.de> Gregor Becker <g.becker@careerpartner.eu>\nCodeDredd <gregor@codedredd.de> Gregor Becker <gregor.becker@getinbyte.com>\n"
  },
  {
    "path": ".php_cs.dist.php",
    "content": "<?php\n\n$finder = Symfony\\Component\\Finder\\Finder::create()\n    ->in([\n        __DIR__ . '/src',\n        __DIR__ . '/tests',\n    ])\n    ->name('*.php')\n    ->notName('*.blade.php')\n    ->ignoreDotFiles(true)\n    ->ignoreVCS(true);\n\nreturn (new PhpCsFixer\\Config())\n    ->setRules([\n        '@PSR12' => true,\n        'array_syntax' => ['syntax' => 'short'],\n        'ordered_imports' => ['sort_algorithm' => 'alpha'],\n        'no_unused_imports' => true,\n        'not_operator_with_successor_space' => true,\n        'trailing_comma_in_multiline' => true,\n        'phpdoc_scalar' => true,\n        'unary_operator_spaces' => true,\n        'binary_operator_spaces' => true,\n        'blank_line_before_statement' => [\n            'statements' => ['break', 'continue', 'declare', 'return', 'throw', 'try'],\n        ],\n        'phpdoc_single_line_var_spacing' => true,\n        'phpdoc_var_without_name' => true,\n        'class_attributes_separation' => [\n            'elements' => [\n                'method' => 'one',\n            ],\n        ],\n        'method_argument_space' => [\n            'on_multiline' => 'ensure_fully_multiline',\n            'keep_multiple_spaces_after_comma' => true,\n        ],\n        'single_trait_insert_per_statement' => true,\n    ])\n    ->setFinder($finder);\n"
  },
  {
    "path": ".styleci.yml",
    "content": "preset: laravel\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2014 Michael van de Rijt\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": "<p align=\"center\">\n  <a href=\"https://codedredd.github.io/laravel-soap/\" target=\"_blank\" rel=\"noopener noreferrer\">\n    <img style=\"width: 100%; height: auto\" width=\"100%\" src=\"https://www.codedredd.de/images/laravel-soap/preview.png\" alt=\"Laravel SOAP\">\n  </a>\n</p>\n\n# Laravel SOAP Client\n\n[![Software License](https://img.shields.io/github/license/codedredd/laravel-soap?style=flat-square)](LICENSE.md)\n[![Total Downloads](https://img.shields.io/packagist/dt/codedredd/laravel-soap?style=flat-square)](https://packagist.org/packages/codedredd/laravel-soap)\n[![test](https://img.shields.io/github/workflow/status/codedredd/laravel-soap/test?label=test&logo=github&style=flat-square)](https://github.com/CodeDredd/laravel-soap/actions?query=workflow%3Atest)\n[![styleci](https://github.styleci.io/repos/7548986/shield)](https://github.styleci.io/repos/257192373)\n[![version](https://img.shields.io/github/v/release/codedredd/laravel-soap?style=flat-square)](https://github.com/CodeDredd/laravel-soap/releases)\n[![documentation](https://img.shields.io/github/workflow/status/codedredd/laravel-soap/documentation?label=docs&logo=read-the-docs&style=flat-square)](https://codedredd.github.io/laravel-soap/)\n\n## Versions\n| Laravel SOAP Version | Laravel Support | PHP Version |\n|----------------------|-----------------|-------------|\n| 1.x                  | 5.6, 6.x, 7.x   | 7.3 - 8.0   |\n| 2.x                  | 8.x             | 7.3 - 8.0   |\n| 3.x                  | 9.x             | 8.0 - 8.1   |\n| 4.x                  | 9.x, 10.x       | 8.1 - 8.2   |\n\n<a name=\"installation\"></a>\n## Installation\n\nExecute the following command to get the latest version of the package:\n\n    composer require codedredd/laravel-soap\n    \n## Documentation\nYou can find here a detailed [documentation](https://codedredd.github.io/laravel-soap/)\n\n## Help me keep working on this project 💚\n\n- [Become a Sponsor on GitHub](https://github.com/sponsors/codedredd)\n- [One-time donation via PayPal](https://paypal.me/dredd1984)\n\n<!--sponsors start-->\n<h3 align=\"center\">Platinum Sponsors</h3>\n<p align=\"center\">\n</p>\n\n<h4 align=\"center\">Gold Sponsors</h4>\n<p align=\"center\">\n</p>\n\n<h4 align=\"center\">Silver Sponsors</h4>\n<p align=\"center\">\n</p>\n\n<h4 align=\"center\">Bronze Sponsors</h4>\n<p align=\"center\">\n</p>\n\n<!--sponsors end-->\n\n---\n\n<a name=\"contributing\"></a>\n## Contributing\nPlease post issues and send PRs.\n\n<a name=\"licence\"></a>\n## License\nLaravel Soap is open-sourced software licensed under the MIT license.\n"
  },
  {
    "path": "composer.json",
    "content": "{\n    \"name\": \"codedredd/laravel-soap\",\n    \"description\": \"A SoapClient wrapper integration for Laravel\",\n    \"keywords\": [\n        \"laravel\",\n        \"soap\",\n        \"client\",\n        \"wrapper\"\n    ],\n    \"license\": \"MIT\",\n    \"authors\": [\n        {\n            \"name\": \"Gregor Becker\",\n            \"email\": \"gregor@codedredd.de\"\n        }\n    ],\n    \"require\": {\n        \"php\": \"~8.1 || ~8.2 || ~8.3 || ~8.4\",\n        \"ext-soap\": \"*\",\n        \"ext-bcmath\": \"*\",\n        \"ext-intl\": \"*\",\n        \"ext-json\": \"*\",\n        \"ext-dom\": \"*\",\n        \"ext-simplexml\": \"*\",\n        \"illuminate/http\": \"^9.0 || ^10.0 || ^11.0 || ^12.0\",\n        \"illuminate/support\": \"^9.0 || ^10.0 || ^11.0 || ^12.0\",\n        \"phpro/soap-client\": \"^2.3.0 || ^3.1.0\",\n        \"php-http/guzzle7-adapter\": \"^1.0\",\n        \"php-http/discovery\": \"^1.14\",\n        \"php-http/message\": \"^1.13\",\n        \"php-http/client-common\": \"^2.6\",\n        \"robrichards/wse-php\": \"^2.0\",\n        \"php-soap/psr18-transport\": \"^1.7\",\n        \"php-soap/psr18-wsse-middleware\": \"^2.6\",\n        \"veewee/xml\": \"^2.6 || ^3.0\",\n        \"spatie/laravel-package-tools\": \"^1.92\",\n        \"illuminate/contracts\": \"^9.0 || ^10.0 || ^11.0 || ^12.0\"\n    },\n    \"require-dev\": {\n        \"symfony/options-resolver\": \"^6.2.5\",\n        \"phpunit/phpunit\": \"^10.0 || ^11.0\",\n        \"orchestra/testbench\": \"^8.0 || ^9.0 || ^10.0\",\n        \"laminas/laminas-code\": \"^4.8.0\",\n        \"nunomaduro/collision\": \"^8.1\",\n        \"symplify/easy-ci\": \"^10.0\",\n        \"spatie/laravel-ray\": \"^1.32\",\n        \"larastan/larastan\": \"^3.1\"\n    },\n    \"autoload\": {\n        \"psr-4\": {\n            \"CodeDredd\\\\Soap\\\\\": \"src/\"\n        }\n    },\n    \"autoload-dev\": {\n        \"psr-4\": {\n            \"CodeDredd\\\\Soap\\\\Tests\\\\\": \"tests/\"\n        }\n    },\n    \"extra\": {\n        \"laravel\": {\n            \"providers\": [\n                \"CodeDredd\\\\Soap\\\\SoapServiceProvider\"\n            ],\n            \"aliases\": {\n                \"SOAP\": \"SoapFacade\"\n            }\n        }\n    },\n    \"minimum-stability\": \"dev\",\n    \"prefer-stable\": true,\n    \"config\": {\n        \"allow-plugins\": {\n            \"php-http/discovery\": true\n        }\n    }\n}\n"
  },
  {
    "path": "config/soap.php",
    "content": "<?php\n\nuse RobRichards\\XMLSecLibs\\XMLSecurityKey;\n\nreturn [\n    /*\n    |--------------------------------------------------------------------------\n    | SOAP Code Generation directory\n    |--------------------------------------------------------------------------\n    |\n    | Define the destination for the code generator under the app directory\n    */\n\n    'code' => [\n        'path' => app_path('Soap'),\n        'namespace' => 'App\\\\Soap',\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | SOAP Ray Configuration\n    |--------------------------------------------------------------------------\n    |\n    | Define if all requests should go to ray\n    */\n\n    'ray' => [\n        'send_soap_client_requests' => false,\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | SOAP Call behaviour\n    |--------------------------------------------------------------------------\n    |\n    | Define if the arguments should be wrapped in an array\n    */\n\n    'call' => [\n        'wrap_arguments_in_array' => true,\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | SOAP Client Configuration\n    |--------------------------------------------------------------------------\n    |\n    | Her you can setup your soap client by configuration so that ou just need\n    | a name.\n    |\n    | example: Soap::buildClient('laravel_soap')\n    */\n\n    'clients' => [\n        'laravel_soap' => [\n            'base_wsdl' => 'test.wsdl',\n            'with_wsa' => true,\n            'with_basic_auth' => [\n                'username' => 'username',\n                'password' => 'password',\n            ],\n            'with_wsse' => [\n                'user_token_name' => 'username',\n                'user_token_password' => 'password',\n                'private_key_file' => 'path/to/privatekey.pem',\n                'public_key_file' => 'path/to/publickey.pyb',\n                'server_certificate_file' => 'path/to/client-cert.pem',\n                'server_certificate_has_subject_key_identifier' => false,\n                'user_token_digest' => false,\n                'digital_sign_method' => XMLSecurityKey::RSA_SHA1,\n                'timestamp' => 3600,\n                'sign_all_headers' => false,\n            ],\n        ],\n    ],\n\n];\n"
  },
  {
    "path": "mkdocs.yml",
    "content": "site_name: Laravel SOAP Docs\nsite_description: 'Laravel SOAP Documentation'\nsite_author: 'Gregor Becker'\ndocs_dir: docs/v2/\nrepo_name: 'codedredd/laravel-soap'\nrepo_url: 'https://github.com/codedredd/laravel-soap'\n\n# Copyright\ncopyright: Copyright &copy; 2020 - 2020 Gregor Becker\n\nnav:\n  - 'Get started': 'index.md'\n  - Client:\n      - Request: 'client/request.md'\n      - Response: 'client/response.md'\n      - authentication: 'client/authentication.md'\n      - configuration: 'client/configuration.md'\n  - Commands: 'commands.md'\n  - Testing: 'testing.md'\ntheme:\n  name: 'material'\n  language: 'en'\n  palette:\n    primary: 'cyan'\n    accent: 'deep orange'\nmarkdown_extensions:\n  - admonition\n  - attr_list\n  - codehilite:\n      guess_lang: false\n  - toc:\n      permalink: true\n  - pymdownx.betterem:\n      smart_enable: all\n  - pymdownx.superfences\n  - pymdownx.inlinehilite\n  - pymdownx.tabbed\n  - pymdownx.emoji:\n      emoji_index: !!python/name:materialx.emoji.twemoji\n      emoji_generator: !!python/name:materialx.emoji.to_svg\n  - pymdownx.highlight:\n      extend_pygments_lang:\n        - name: php-inline\n          lang: php\n          options:\n            startinline: true\n"
  },
  {
    "path": "src/Client/Events/ConnectionFailed.php",
    "content": "<?php\n\nnamespace CodeDredd\\Soap\\Client\\Events;\n\nuse CodeDredd\\Soap\\Client\\Request;\n\nclass ConnectionFailed\n{\n    /**\n     * The request instance.\n     *\n     * @var \\CodeDredd\\Soap\\Client\\Request\n     */\n    public $request;\n\n    /**\n     * Create a new event instance.\n     *\n     * @param  \\CodeDredd\\Soap\\Client\\Request  $request\n     * @return void\n     */\n    public function __construct(Request $request)\n    {\n        $this->request = $request;\n    }\n}\n"
  },
  {
    "path": "src/Client/Events/RequestSending.php",
    "content": "<?php\n\nnamespace CodeDredd\\Soap\\Client\\Events;\n\nuse CodeDredd\\Soap\\Client\\Request;\n\nclass RequestSending\n{\n    /**\n     * The request instance.\n     */\n    public Request $request;\n\n    /**\n     * Create a new event instance.\n     *\n     * @param  Request  $request\n     * @return void\n     */\n    public function __construct(Request $request)\n    {\n        $this->request = $request;\n    }\n}\n"
  },
  {
    "path": "src/Client/Events/ResponseReceived.php",
    "content": "<?php\n\nnamespace CodeDredd\\Soap\\Client\\Events;\n\nuse CodeDredd\\Soap\\Client\\Request;\nuse CodeDredd\\Soap\\Client\\Response;\n\nclass ResponseReceived\n{\n    /**\n     * The request instance.\n     *\n     * @var \\CodeDredd\\Soap\\Client\\Request\n     */\n    public Request $request;\n\n    /**\n     * The response instance.\n     *\n     * @var \\CodeDredd\\Soap\\Client\\Response\n     */\n    public Response $response;\n\n    /**\n     * Create a new event instance.\n     *\n     * @param  \\CodeDredd\\Soap\\Client\\Request  $request\n     * @param  \\CodeDredd\\Soap\\Client\\Response  $response\n     * @return void\n     */\n    public function __construct(Request $request, Response $response)\n    {\n        $this->request = $request;\n        $this->response = $response;\n    }\n}\n"
  },
  {
    "path": "src/Client/Request.php",
    "content": "<?php\n\nnamespace CodeDredd\\Soap\\Client;\n\nuse Illuminate\\Support\\Arr;\nuse Illuminate\\Support\\Str;\nuse Illuminate\\Support\\Traits\\Macroable;\nuse LogicException;\nuse Psr\\Http\\Message\\RequestInterface;\nuse Soap\\Psr18Transport\\HttpBinding\\SoapActionDetector;\nuse Soap\\Xml\\Locator\\SoapBodyLocator;\nuse VeeWee\\Xml\\Dom\\Document;\nuse VeeWee\\Xml\\Dom\\Traverser\\Visitor\\RemoveNamespaces;\nuse VeeWee\\Xml\\Encoding\\Exception\\EncodingException;\n\nuse function VeeWee\\Xml\\Dom\\Configurator\\traverse;\nuse function VeeWee\\Xml\\Encoding\\element_decode;\n\n/**\n * Class Request.\n */\nclass Request\n{\n    use Macroable;\n\n    /**\n     * The underlying PSR request.\n     */\n    protected RequestInterface $request;\n\n    /**\n     * The decoded payload for the request.\n     */\n    protected array $data;\n\n    /**\n     * Create a new request instance.\n     *\n     * @param  RequestInterface  $request\n     * @return void\n     */\n    public function __construct($request)\n    {\n        $this->request = $request;\n    }\n\n    /**\n     * Get the soap action for soap 1.1 and 1.2.\n     */\n    public function action(): string\n    {\n        return Str::remove('\"', SoapActionDetector::detectFromRequest($this->request));\n    }\n\n    public function getRequest(): RequestInterface\n    {\n        return $this->request;\n    }\n\n    /**\n     * Get the URL of the request.\n     */\n    public function url(): string\n    {\n        return (string) $this->request->getUri();\n    }\n\n    /**\n     * Determine if the request has a given header.\n     *\n     * @param  string  $key\n     * @param  mixed  $value\n     * @return bool\n     */\n    public function hasHeader($key, $value = null)\n    {\n        if (is_null($value)) {\n            return ! empty($this->request->getHeaders()[$key]);\n        }\n\n        $headers = $this->headers();\n\n        if (! Arr::has($headers, $key)) {\n            return false;\n        }\n\n        $value = is_array($value) ? $value : [$value];\n\n        return empty(array_diff($value, $headers[$key]));\n    }\n\n    /**\n     * Determine if the request has the given headers.\n     *\n     * @param  array|string  $headers\n     * @return bool\n     */\n    public function hasHeaders($headers)\n    {\n        if (is_string($headers)) {\n            $headers = [$headers => null];\n        }\n\n        foreach ($headers as $key => $value) {\n            if (! $this->hasHeader($key, $value)) {\n                return false;\n            }\n        }\n\n        return true;\n    }\n\n    /**\n     * Get the values for the header with the given name.\n     *\n     * @param  string  $key\n     * @return array\n     */\n    public function header($key)\n    {\n        return Arr::get($this->headers(), $key, []);\n    }\n\n    /**\n     * Get the request headers.\n     *\n     * @return array\n     */\n    public function headers()\n    {\n        return $this->request->getHeaders();\n    }\n\n    /**\n     * Get the body of the request.\n     *\n     * @return string\n     */\n    public function body()\n    {\n        return (string) $this->request->getBody();\n    }\n\n    /**\n     * Return complete xml request body.\n     */\n    public function xmlContent(): string\n    {\n        return $this->request->getBody()->getContents();\n    }\n\n    /**\n     * Return request arguments.\n     *\n     * @throws EncodingException\n     */\n    public function arguments(): array\n    {\n        $doc = Document::fromXmlString($this->body());\n        $wrappedArguments = config()->get('soap.call.wrap_arguments_in_array', true);\n        $method = $doc->locate(new SoapBodyLocator());\n\n        if ($wrappedArguments) {\n            $method = $method?->firstElementChild;\n        }\n\n        return Arr::wrap(Arr::get(element_decode($method, traverse(new RemoveNamespaces())), $wrappedArguments ? 'node' : 'Body', []));\n    }\n\n    /**\n     * Set the decoded data on the request.\n     *\n     * @param  array  $data\n     * @return $this\n     */\n    public function withData(array $data)\n    {\n        $this->data = $data;\n\n        return $this;\n    }\n\n    /**\n     * Get the underlying PSR compliant request instance.\n     *\n     * @return \\Psr\\Http\\Message\\RequestInterface\n     */\n    public function toPsrRequest()\n    {\n        return $this->request;\n    }\n\n    /**\n     * Determine if the given offset exists.\n     *\n     * @param  string  $offset\n     * @return bool\n     *\n     * @throws EncodingException\n     */\n    public function offsetExists(string $offset): bool\n    {\n        return isset($this->arguments()[$offset]);\n    }\n\n    /**\n     * Get the value for a given offset.\n     *\n     * @param  string  $offset\n     * @return mixed\n     *\n     * @throws EncodingException\n     */\n    public function offsetGet($offset): mixed\n    {\n        return $this->arguments()[$offset];\n    }\n\n    /**\n     * Set the value at the given offset.\n     *\n     * @param  string  $offset\n     * @param  mixed  $value\n     * @return void\n     *\n     * @throws LogicException\n     */\n    public function offsetSet($offset, $value): void\n    {\n        throw new LogicException('Request data may not be mutated using array access.');\n    }\n\n    /**\n     * Unset the value at the given offset.\n     *\n     * @param  string  $offset\n     * @return void\n     *\n     * @throws LogicException\n     */\n    public function offsetUnset($offset): void\n    {\n        throw new LogicException('Request data may not be mutated using array access.');\n    }\n}\n"
  },
  {
    "path": "src/Client/Response.php",
    "content": "<?php\n\nnamespace CodeDredd\\Soap\\Client;\n\nuse ArrayAccess;\nuse CodeDredd\\Soap\\Exceptions\\RequestException;\nuse GuzzleHttp\\Psr7\\Response as Psr7Response;\nuse GuzzleHttp\\TransferStats;\nuse Illuminate\\Support\\Collection;\nuse Illuminate\\Support\\Str;\nuse Illuminate\\Support\\Traits\\Macroable;\nuse LogicException;\nuse Phpro\\SoapClient\\Type\\ResultInterface;\nuse Psr\\Http\\Message\\ResponseInterface;\nuse VeeWee\\Xml\\Dom\\Document;\n\nuse function Psl\\Type\\string;\n\n/**\n * Class Response.\n */\nclass Response implements ResultInterface, ArrayAccess\n{\n    use Macroable {\n        __call as macroCall;\n    }\n    protected ?TransferStats $transferStats = null;\n\n    protected array $cookies = [];\n\n    /**\n     * The underlying PSR response.\n     */\n    protected ResponseInterface $response;\n\n    /**\n     * The decoded JSON response.\n     *\n     * @var array\n     */\n    protected $decoded;\n\n    /**\n     * Create a new response instance.\n     */\n    public function __construct(ResponseInterface $response)\n    {\n        $this->response = $response;\n    }\n\n    public function setCookies(array $cookies): void\n    {\n        $this->cookies = $cookies;\n    }\n\n    public function setTransferStats(?TransferStats $transferStats): void\n    {\n        $this->transferStats = $transferStats;\n    }\n\n    public static function fromSoapResponse(mixed $result, int $status = 200): Response\n    {\n        return new self(new Psr7Response($status, [], json_encode($result)));\n    }\n\n    public static function fromSoapFault(\\SoapFault $soapFault): Response\n    {\n        return new self(new Psr7Response(400, [], $soapFault->getMessage()));\n    }\n\n    /**\n     * Get the underlying PSR response for the response.\n     */\n    public function toPsrResponse(): ResponseInterface\n    {\n        return $this->response;\n    }\n\n    /**\n     * Get the JSON decoded body of the response as an object.\n     *\n     * @return object\n     */\n    public function object(): object\n    {\n        return json_decode($this->body(), false);\n    }\n\n    /**\n     * Get the JSON decoded body of the response as a collection.\n     *\n     * @param  string|null  $key\n     * @return \\Illuminate\\Support\\Collection\n     */\n    public function collect(string $key = null): Collection\n    {\n        return Collection::make($this->json($key));\n    }\n\n    /**\n     * Get the body of the response.\n     *\n     * @param  bool  $transformXml\n     * @param  bool  $sanitizeXmlFaultMessage\n     * @return string\n     */\n    public function body(bool $transformXml = true, bool $sanitizeXmlFaultMessage = true): string\n    {\n        $body = (string) $this->response->getBody();\n        if ($transformXml && Str::contains($body, '<?xml')) {\n            $message = Document::fromXmlString($body)\n                    ->xpath()\n                    ->evaluate('string(.//faultstring)', string())\n                ?? 'No Fault Message found';\n\n            return trim($sanitizeXmlFaultMessage ? Str::after($message, 'Exception:') : $message);\n        }\n\n        return $body;\n    }\n\n    /**\n     * Determine if the request was successful.\n     *\n     * @return bool\n     */\n    public function successful(): bool\n    {\n        return $this->status() >= 200 && $this->status() < 300;\n    }\n\n    /**\n     * Get the status code of the response.\n     *\n     * @return int\n     */\n    public function status(): int\n    {\n        return (int) $this->response->getStatusCode();\n    }\n\n    /**\n     * Determine if the response code was \"OK\".\n     */\n    public function ok(): bool\n    {\n        return $this->status() === 200;\n    }\n\n    /**\n     * Determine if the response indicates a client or server error occurred.\n     */\n    public function failed(): bool\n    {\n        return $this->serverError() || $this->clientError();\n    }\n\n    /**\n     * Determine if the response was a redirect.\n     */\n    public function redirect(): bool\n    {\n        return $this->status() >= 300 && $this->status() < 400;\n    }\n\n    /**\n     * Throw an exception if a server or client error occurred.\n     *\n     * @return $this\n     *\n     * @throws \\CodeDredd\\Soap\\Exceptions\\RequestException\n     */\n    public function throw()\n    {\n        $callback = func_get_args()[0] ?? null;\n\n        if ($this->failed()) {\n            throw tap(new RequestException($this), function ($exception) use ($callback) {\n                if ($callback && is_callable($callback)) {\n                    $callback($this, $exception);\n                }\n            });\n        }\n\n        return $this;\n    }\n\n    /**\n     * Throw an exception if a server or client error occurred and the given condition evaluates to true.\n     *\n     * @param  bool  $condition\n     * @return $this\n     *\n     * @throws \\CodeDredd\\Soap\\Exceptions\\RequestException\n     */\n    public function throwIf(bool $condition): Response|static\n    {\n        return $condition ? $this->throw() : $this;\n    }\n\n    /**\n     * Determine if the response indicates a server error occurred.\n     */\n    public function serverError(): bool\n    {\n        return $this->status() >= 500;\n    }\n\n    /**\n     * Determine if the response indicates a client error occurred.\n     */\n    public function clientError(): bool\n    {\n        return $this->status() >= 400 && $this->status() < 500;\n    }\n\n    /**\n     * Execute the given callback if there was a server or client error.\n     *\n     * @param  \\Closure|callable  $callback\n     * @return \\CodeDredd\\Soap\\Client\\Response\n     */\n    public function onError(callable $callback)\n    {\n        if ($this->failed()) {\n            $callback($this);\n        }\n\n        return $this;\n    }\n\n    /**\n     * Get the handler stats of the response.\n     *\n     * @return array\n     */\n    public function handlerStats()\n    {\n        return $this->transferStats?->getHandlerStats() ?? [];\n    }\n\n    /**\n     * Get the JSON decoded body of the response as an array.\n     */\n    public function json($key = null, $default = null): ?array\n    {\n        if (! $this->decoded) {\n            $this->decoded = json_decode($this->body(), true);\n        }\n\n        if (is_null($key)) {\n            return $this->decoded;\n        }\n\n        return data_get($this->decoded, $key, $default);\n    }\n\n    /**\n     * Get a header from the response.\n     */\n    public function header(string $header): string\n    {\n        return $this->response->getHeaderLine($header);\n    }\n\n    /**\n     * Get the headers from the response.\n     */\n    public function headers(): array\n    {\n        return $this->response->getHeaders();\n    }\n\n    /**\n     * Determine if the given offset exists.\n     *\n     * @param  string  $offset\n     * @return bool\n     */\n    public function offsetExists($offset): bool\n    {\n        return isset($this->json()[$offset]);\n    }\n\n    /**\n     * Get the value for a given offset.\n     *\n     * @param  string  $offset\n     * @return mixed\n     */\n    public function offsetGet($offset): mixed\n    {\n        return $this->json()[$offset];\n    }\n\n    /**\n     * Set the value at the given offset.\n     *\n     * @param  string  $offset\n     * @param  mixed  $value\n     * @return void\n     *\n     * @throws \\LogicException\n     */\n    public function offsetSet($offset, $value): void\n    {\n        throw new LogicException('Response data may not be mutated using array access.');\n    }\n\n    /**\n     * Unset the value at the given offset.\n     *\n     * @param  string  $offset\n     * @return void\n     *\n     * @throws \\LogicException\n     */\n    public function offsetUnset($offset): void\n    {\n        throw new LogicException('Response data may not be mutated using array access.');\n    }\n\n    /**\n     * Get the body of the response.\n     *\n     * @return string\n     */\n    public function __toString()\n    {\n        return $this->body();\n    }\n\n    /**\n     * Dynamically proxy other methods to the underlying response.\n     *\n     * @param  string  $method\n     * @param  array  $parameters\n     * @return mixed\n     */\n    public function __call($method, $parameters)\n    {\n        return static::hasMacro($method)\n            ? $this->macroCall($method, $parameters)\n            : $this->response->{$method}(...$parameters);\n    }\n}\n"
  },
  {
    "path": "src/Client/ResponseSequence.php",
    "content": "<?php\n\nnamespace CodeDredd\\Soap\\Client;\n\nuse CodeDredd\\Soap\\SoapFactory;\nuse OutOfBoundsException;\n\nclass ResponseSequence\n{\n    /**\n     * The responses in the sequence.\n     *\n     * @var array\n     */\n    protected $responses;\n\n    /**\n     * Indicates that invoking this sequence when it is empty should throw an exception.\n     *\n     * @var bool\n     */\n    protected $failWhenEmpty = true;\n\n    /**\n     * The response that should be returned when the sequence is empty.\n     *\n     * @var ?\\GuzzleHttp\\Promise\\PromiseInterface\n     */\n    protected ?\\GuzzleHttp\\Promise\\PromiseInterface $emptyResponse = null;\n\n    /**\n     * Create a new response sequence.\n     *\n     * @param  array  $responses\n     * @return void\n     */\n    public function __construct(array $responses)\n    {\n        $this->responses = $responses;\n    }\n\n    /**\n     * Push a response to the sequence.\n     *\n     * @param  string|array  $body\n     * @param  int  $status\n     * @param  array  $headers\n     * @return $this\n     */\n    public function push($body = '', int $status = 200, array $headers = [])\n    {\n        return $this->pushResponse(\n            SoapFactory::response($body, $status, $headers)\n        );\n    }\n\n    /**\n     * Push a response to the sequence.\n     *\n     * @param  mixed  $response\n     * @return $this\n     */\n    public function pushResponse($response)\n    {\n        $this->responses[] = $response;\n\n        return $this;\n    }\n\n    /**\n     * Push a response with the given status code to the sequence.\n     *\n     * @param  int  $status\n     * @param  array  $headers\n     * @return $this\n     */\n    public function pushStatus(int $status, array $headers = [])\n    {\n        return $this->pushResponse(\n            SoapFactory::response('', $status, $headers)\n        );\n    }\n\n    /**\n     * Push response with the contents of a file as the body to the sequence.\n     *\n     * @param  string  $filePath\n     * @param  int  $status\n     * @param  array  $headers\n     * @return $this\n     */\n    public function pushFile(string $filePath, int $status = 200, array $headers = [])\n    {\n        $string = file_get_contents($filePath);\n\n        return $this->pushResponse(\n            SoapFactory::response($string, $status, $headers)\n        );\n    }\n\n    /**\n     * Make the sequence return a default response when it is empty.\n     *\n     * @return $this\n     */\n    public function dontFailWhenEmpty()\n    {\n        return $this->whenEmpty(SoapFactory::response());\n    }\n\n    /**\n     * Make the sequence return a default response when it is empty.\n     *\n     * @param  \\GuzzleHttp\\Promise\\PromiseInterface|\\Closure  $response\n     * @return $this\n     */\n    public function whenEmpty($response)\n    {\n        $this->failWhenEmpty = false;\n        $this->emptyResponse = $response;\n\n        return $this;\n    }\n\n    /**\n     * Indicate that this sequence has depleted all of its responses.\n     *\n     * @return bool\n     */\n    public function isEmpty()\n    {\n        return count($this->responses) === 0;\n    }\n\n    /**\n     * Get the next response in the sequence.\n     *\n     * @return mixed\n     */\n    public function __invoke()\n    {\n        if ($this->failWhenEmpty && count($this->responses) === 0) {\n            throw new OutOfBoundsException('A request was made, but the response sequence is empty.');\n        }\n\n        if (! $this->failWhenEmpty && count($this->responses) === 0) {\n            return value($this->emptyResponse ?? SoapFactory::response());\n        }\n\n        return array_shift($this->responses);\n    }\n}\n"
  },
  {
    "path": "src/Driver/ExtSoap/ExtSoapEngineFactory.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace CodeDredd\\Soap\\Driver\\ExtSoap;\n\nuse CodeDredd\\Soap\\Faker\\EngineFaker;\nuse Soap\\Engine\\SimpleEngine;\nuse Soap\\Engine\\Transport;\nuse Soap\\ExtSoapEngine\\ExtSoapDriver;\nuse Soap\\ExtSoapEngine\\ExtSoapOptions;\n\nclass ExtSoapEngineFactory\n{\n    public static function fromOptionsWithHandler(\n        ExtSoapOptions $options,\n        Transport $transport,\n        $withMocking = false\n    ): EngineFaker|SimpleEngine {\n        $driver = ExtSoapDriver::createFromOptions($options);\n        if ($withMocking) {\n        }\n\n        return $withMocking ? new EngineFaker($driver, $transport, $options) : new SimpleEngine($driver, $transport);\n    }\n}\n"
  },
  {
    "path": "src/Exceptions/NotFoundConfigurationException.php",
    "content": "<?php\n\nnamespace CodeDredd\\Soap\\Exceptions;\n\nuse RuntimeException;\n\nclass NotFoundConfigurationException extends RuntimeException\n{\n    /**\n     * @param  \\Throwable  $throwable\n     * @return NotFoundConfigurationException\n     */\n    public static function fromThrowable(\\Throwable $throwable): self\n    {\n        return new self($throwable->getMessage(), (int) $throwable->getCode(), $throwable);\n    }\n}\n"
  },
  {
    "path": "src/Exceptions/RequestException.php",
    "content": "<?php\n\nnamespace CodeDredd\\Soap\\Exceptions;\n\nuse CodeDredd\\Soap\\Client\\Response;\nuse Exception;\n\nclass RequestException extends Exception\n{\n    /**\n     * The response instance.\n     *\n     * @var \\CodeDredd\\Soap\\Client\\Response\n     */\n    public $response;\n\n    /**\n     * Create a new exception instance.\n     *\n     * @param  \\CodeDredd\\Soap\\Client\\Response  $response\n     * @return void\n     */\n    public function __construct(Response $response)\n    {\n        parent::__construct(\n            \"Soap request error with status code {$response->status()}:\\n {$response->body()}\",\n            $response->status()\n        );\n\n        $this->response = $response;\n    }\n}\n"
  },
  {
    "path": "src/Exceptions/SoapException.php",
    "content": "<?php\n\nnamespace CodeDredd\\Soap\\Exceptions;\n\n/**\n * Class SoapException.\n */\nclass SoapException extends \\RuntimeException\n{\n    /**\n     * @param  \\Throwable  $throwable\n     * @return SoapException\n     */\n    public static function fromThrowable(\\Throwable $throwable): self\n    {\n        return new self($throwable->getMessage(), (int) $throwable->getCode(), $throwable);\n    }\n}\n"
  },
  {
    "path": "src/Facades/Soap.php",
    "content": "<?php\n\nnamespace CodeDredd\\Soap\\Facades;\n\nuse CodeDredd\\Soap\\SoapFactory;\nuse Illuminate\\Support\\Facades\\Facade;\n\n/**\n * Class Soap.\n *\n * @method static \\CodeDredd\\Soap\\Handler\\HttPlugHandle getHandler()\n * @method static \\CodeDredd\\Soap\\SoapClient baseWsdl(string $wsdl)\n * @method static \\CodeDredd\\Soap\\SoapClient stub(callable $callback)\n * @method static \\CodeDredd\\Soap\\SoapClient buildClient(string $setup = '')\n * @method static \\CodeDredd\\Soap\\SoapClient byConfig(string $setup = '')\n * @method static \\CodeDredd\\Soap\\SoapClient withOptions(array $options)\n * @method static \\CodeDredd\\Soap\\SoapClient withHeaders(array $options)\n * @method static \\CodeDredd\\Soap\\SoapClient withGuzzleClientOptions(array $options)\n * @method static \\CodeDredd\\Soap\\SoapClient withWsse(array $config)\n * @method static \\CodeDredd\\Soap\\SoapClient withWsa()\n * @method static \\CodeDredd\\Soap\\SoapClient withRemoveEmptyNodes()\n * @method static \\CodeDredd\\Soap\\SoapClient withBasicAuth(string $username, string $password)\n * @method static \\CodeDredd\\Soap\\SoapClient withCisDHLAuth($user, ?string $signature = null)\n * @method \\CodeDredd\\Soap\\Client\\Response call(string $method, array $arguments = [])\n * @method static \\GuzzleHttp\\Promise\\PromiseInterface response($body = null, $status = 200, array $headers = [])\n * @method static \\CodeDredd\\Soap\\Client\\ResponseSequence sequence(array $responses = [])\n * @method static \\CodeDredd\\Soap\\Client\\ResponseSequence fakeSequence(string $urlPattern = '*')\n * @method static \\CodeDredd\\Soap\\SoapFactory fake($callback = null)\n * @method static assertSent(callable $callback)\n * @method static assertNotSent(callable $callback)\n * @method static assertActionCalled(string $action)\n * @method static assertNothingSent()\n * @method static assertSequencesAreEmpty()\n * @method static assertSentCount($count)\n */\nclass Soap extends Facade\n{\n    /**\n     * {@inheritdoc}\n     */\n    protected static function getFacadeAccessor()\n    {\n        return SoapFactory::class;\n    }\n}\n"
  },
  {
    "path": "src/Faker/EngineFaker.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace CodeDredd\\Soap\\Faker;\n\nuse CodeDredd\\Soap\\Xml\\XMLSerializer;\nuse Soap\\Engine\\Driver;\nuse Soap\\Engine\\Engine;\nuse Soap\\Engine\\HttpBinding\\SoapRequest;\nuse Soap\\Engine\\Metadata\\Metadata;\nuse Soap\\Engine\\Transport;\nuse Soap\\ExtSoapEngine\\ExtSoapOptions;\n\n/**\n * Class EngineFaker.\n */\nclass EngineFaker implements Engine\n{\n    private Driver $driver;\n    private Transport $transport;\n    private ExtSoapOptions $options;\n\n    public function __construct(\n        Driver $driver,\n        Transport $transport,\n        ExtSoapOptions $options\n    ) {\n        $this->driver = $driver;\n        $this->transport = $transport;\n        $this->options = $options;\n    }\n\n    public function request(string $method, array $arguments)\n    {\n        $request = new SoapRequest(XMLSerializer::arrayToSoapXml($arguments), $this->options->getWsdl(), $method, $this->options->getOptions()['soap_version'] ?? SOAP_1_1);\n        $response = $this->transport->request($request);\n\n        return json_decode($response->getPayload());\n    }\n\n    public function getMetadata(): Metadata\n    {\n        return $this->driver->getMetadata();\n    }\n}\n"
  },
  {
    "path": "src/Faker/fake.wsdl",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<!--\r\nCached version of: http://wsf.cdyne.com/WeatherWS/Weather.asmx?wsdl\r\n-->\r\n<wsdl:definitions xmlns:s=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap12=\"http://schemas.xmlsoap.org/wsdl/soap12/\" xmlns:mime=\"http://schemas.xmlsoap.org/wsdl/mime/\" xmlns:tns=\"http://ws.cdyne.com/WeatherWS/\" xmlns:soap=\"http://schemas.xmlsoap.org/wsdl/soap/\" xmlns:tm=\"http://microsoft.com/wsdl/mime/textMatching/\" xmlns:http=\"http://schemas.xmlsoap.org/wsdl/http/\" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\" targetNamespace=\"http://ws.cdyne.com/WeatherWS/\" xmlns:wsdl=\"http://schemas.xmlsoap.org/wsdl/\">\r\n    <wsdl:types>\r\n        <s:schema elementFormDefault=\"qualified\" targetNamespace=\"http://ws.cdyne.com/WeatherWS/\">\r\n            <s:element name=\"GetWeatherInformation\">\r\n                <s:complexType />\r\n            </s:element>\r\n            <s:element name=\"GetWeatherInformationResponse\">\r\n                <s:complexType>\r\n                    <s:sequence>\r\n                        <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"GetWeatherInformationResult\" type=\"tns:ArrayOfWeatherDescription\" />\r\n                    </s:sequence>\r\n                </s:complexType>\r\n            </s:element>\r\n            <s:complexType name=\"ArrayOfWeatherDescription\">\r\n                <s:sequence>\r\n                    <s:element minOccurs=\"0\" maxOccurs=\"unbounded\" name=\"WeatherDescription\" type=\"tns:WeatherDescription\" />\r\n                </s:sequence>\r\n            </s:complexType>\r\n            <s:complexType name=\"WeatherDescription\">\r\n                <s:sequence>\r\n                    <s:element minOccurs=\"1\" maxOccurs=\"1\" name=\"WeatherID\" type=\"s:short\" />\r\n                    <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"Description\" type=\"s:string\" />\r\n                    <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"PictureURL\" type=\"s:string\" />\r\n                </s:sequence>\r\n            </s:complexType>\r\n            <s:element name=\"GetCityForecastByZIP\">\r\n                <s:complexType>\r\n                    <s:sequence>\r\n                        <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"ZIP\" type=\"s:string\" />\r\n                    </s:sequence>\r\n                </s:complexType>\r\n            </s:element>\r\n            <s:element name=\"GetCityForecastByZIPResponse\">\r\n                <s:complexType>\r\n                    <s:sequence>\r\n                        <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"GetCityForecastByZIPResult\" type=\"tns:ForecastReturn\" />\r\n                    </s:sequence>\r\n                </s:complexType>\r\n            </s:element>\r\n            <s:complexType name=\"ForecastReturn\">\r\n                <s:sequence>\r\n                    <s:element minOccurs=\"1\" maxOccurs=\"1\" name=\"Success\" type=\"s:boolean\" />\r\n                    <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"ResponseText\" type=\"s:string\" />\r\n                    <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"State\" type=\"s:string\" />\r\n                    <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"City\" type=\"s:string\" />\r\n                    <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"WeatherStationCity\" type=\"s:string\" />\r\n                    <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"ForecastResult\" type=\"tns:ArrayOfForecast\" />\r\n                </s:sequence>\r\n            </s:complexType>\r\n            <s:complexType name=\"ArrayOfForecast\">\r\n                <s:sequence>\r\n                    <s:element minOccurs=\"0\" maxOccurs=\"unbounded\" name=\"Forecast\" nillable=\"true\" type=\"tns:Forecast\" />\r\n                </s:sequence>\r\n            </s:complexType>\r\n            <s:complexType name=\"Forecast\">\r\n                <s:sequence>\r\n                    <s:element minOccurs=\"1\" maxOccurs=\"1\" name=\"Date\" type=\"s:dateTime\" />\r\n                    <s:element minOccurs=\"1\" maxOccurs=\"1\" name=\"WeatherID\" type=\"s:short\" />\r\n                    <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"Desciption\" type=\"s:string\" />\r\n                    <s:element minOccurs=\"1\" maxOccurs=\"1\" name=\"Temperatures\" type=\"tns:temp\" />\r\n                    <s:element minOccurs=\"1\" maxOccurs=\"1\" name=\"ProbabilityOfPrecipiation\" type=\"tns:POP\" />\r\n                </s:sequence>\r\n            </s:complexType>\r\n            <s:complexType name=\"temp\">\r\n                <s:sequence>\r\n                    <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"MorningLow\" type=\"s:string\" />\r\n                    <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"DaytimeHigh\" type=\"s:string\" />\r\n                </s:sequence>\r\n            </s:complexType>\r\n            <s:complexType name=\"POP\">\r\n                <s:sequence>\r\n                    <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"Nighttime\" type=\"s:string\" />\r\n                    <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"Daytime\" type=\"s:string\" />\r\n                </s:sequence>\r\n            </s:complexType>\r\n            <s:element name=\"GetCityWeatherByZIP\">\r\n                <s:complexType>\r\n                    <s:sequence>\r\n                        <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"ZIP\" type=\"s:string\" />\r\n                    </s:sequence>\r\n                </s:complexType>\r\n            </s:element>\r\n            <s:element name=\"GetCityWeatherByZIPResponse\">\r\n                <s:complexType>\r\n                    <s:sequence>\r\n                        <s:element minOccurs=\"1\" maxOccurs=\"1\" name=\"GetCityWeatherByZIPResult\" type=\"tns:WeatherReturn\" />\r\n                    </s:sequence>\r\n                </s:complexType>\r\n            </s:element>\r\n            <s:complexType name=\"WeatherReturn\">\r\n                <s:sequence>\r\n                    <s:element minOccurs=\"1\" maxOccurs=\"1\" name=\"Success\" type=\"s:boolean\" />\r\n                    <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"ResponseText\" type=\"s:string\" />\r\n                    <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"State\" type=\"s:string\" />\r\n                    <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"City\" type=\"s:string\" />\r\n                    <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"WeatherStationCity\" type=\"s:string\" />\r\n                    <s:element minOccurs=\"1\" maxOccurs=\"1\" name=\"WeatherID\" type=\"s:short\" />\r\n                    <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"Description\" type=\"s:string\" />\r\n                    <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"Temperature\" type=\"s:string\" />\r\n                    <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"RelativeHumidity\" type=\"s:string\" />\r\n                    <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"Wind\" type=\"s:string\" />\r\n                    <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"Pressure\" type=\"s:string\" />\r\n                    <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"Visibility\" type=\"s:string\" />\r\n                    <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"WindChill\" type=\"s:string\" />\r\n                    <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"Remarks\" type=\"s:string\" />\r\n                </s:sequence>\r\n            </s:complexType>\r\n            <s:element name=\"ArrayOfWeatherDescription\" nillable=\"true\" type=\"tns:ArrayOfWeatherDescription\" />\r\n            <s:element name=\"ForecastReturn\" nillable=\"true\" type=\"tns:ForecastReturn\" />\r\n            <s:element name=\"WeatherReturn\" type=\"tns:WeatherReturn\" />\r\n        </s:schema>\r\n    </wsdl:types>\r\n    <wsdl:message name=\"GetWeatherInformationSoapIn\">\r\n        <wsdl:part name=\"parameters\" element=\"tns:GetWeatherInformation\" />\r\n    </wsdl:message>\r\n    <wsdl:message name=\"GetWeatherInformationSoapOut\">\r\n        <wsdl:part name=\"parameters\" element=\"tns:GetWeatherInformationResponse\" />\r\n    </wsdl:message>\r\n    <wsdl:message name=\"GetCityForecastByZIPSoapIn\">\r\n        <wsdl:part name=\"parameters\" element=\"tns:GetCityForecastByZIP\" />\r\n    </wsdl:message>\r\n    <wsdl:message name=\"GetCityForecastByZIPSoapOut\">\r\n        <wsdl:part name=\"parameters\" element=\"tns:GetCityForecastByZIPResponse\" />\r\n    </wsdl:message>\r\n    <wsdl:message name=\"GetCityWeatherByZIPSoapIn\">\r\n        <wsdl:part name=\"parameters\" element=\"tns:GetCityWeatherByZIP\" />\r\n    </wsdl:message>\r\n    <wsdl:message name=\"GetCityWeatherByZIPSoapOut\">\r\n        <wsdl:part name=\"parameters\" element=\"tns:GetCityWeatherByZIPResponse\" />\r\n    </wsdl:message>\r\n    <wsdl:message name=\"GetWeatherInformationHttpGetIn\" />\r\n    <wsdl:message name=\"GetWeatherInformationHttpGetOut\">\r\n        <wsdl:part name=\"Body\" element=\"tns:ArrayOfWeatherDescription\" />\r\n    </wsdl:message>\r\n    <wsdl:message name=\"GetCityForecastByZIPHttpGetIn\">\r\n        <wsdl:part name=\"ZIP\" type=\"s:string\" />\r\n    </wsdl:message>\r\n    <wsdl:message name=\"GetCityForecastByZIPHttpGetOut\">\r\n        <wsdl:part name=\"Body\" element=\"tns:ForecastReturn\" />\r\n    </wsdl:message>\r\n    <wsdl:message name=\"GetCityWeatherByZIPHttpGetIn\">\r\n        <wsdl:part name=\"ZIP\" type=\"s:string\" />\r\n    </wsdl:message>\r\n    <wsdl:message name=\"GetCityWeatherByZIPHttpGetOut\">\r\n        <wsdl:part name=\"Body\" element=\"tns:WeatherReturn\" />\r\n    </wsdl:message>\r\n    <wsdl:message name=\"GetWeatherInformationHttpPostIn\" />\r\n    <wsdl:message name=\"GetWeatherInformationHttpPostOut\">\r\n        <wsdl:part name=\"Body\" element=\"tns:ArrayOfWeatherDescription\" />\r\n    </wsdl:message>\r\n    <wsdl:message name=\"GetCityForecastByZIPHttpPostIn\">\r\n        <wsdl:part name=\"ZIP\" type=\"s:string\" />\r\n    </wsdl:message>\r\n    <wsdl:message name=\"GetCityForecastByZIPHttpPostOut\">\r\n        <wsdl:part name=\"Body\" element=\"tns:ForecastReturn\" />\r\n    </wsdl:message>\r\n    <wsdl:message name=\"GetCityWeatherByZIPHttpPostIn\">\r\n        <wsdl:part name=\"ZIP\" type=\"s:string\" />\r\n    </wsdl:message>\r\n    <wsdl:message name=\"GetCityWeatherByZIPHttpPostOut\">\r\n        <wsdl:part name=\"Body\" element=\"tns:WeatherReturn\" />\r\n    </wsdl:message>\r\n    <wsdl:portType name=\"WeatherSoap\">\r\n        <wsdl:operation name=\"GetWeatherInformation\">\r\n            <wsdl:documentation xmlns:wsdl=\"http://schemas.xmlsoap.org/wsdl/\">Gets Information for each WeatherID</wsdl:documentation>\r\n            <wsdl:input message=\"tns:GetWeatherInformationSoapIn\" />\r\n            <wsdl:output message=\"tns:GetWeatherInformationSoapOut\" />\r\n        </wsdl:operation>\r\n        <wsdl:operation name=\"GetCityForecastByZIP\">\r\n            <wsdl:documentation xmlns:wsdl=\"http://schemas.xmlsoap.org/wsdl/\">Allows you to get your City Forecast Over the Next 7 Days, which is updated hourly. U.S. Only</wsdl:documentation>\r\n            <wsdl:input message=\"tns:GetCityForecastByZIPSoapIn\" />\r\n            <wsdl:output message=\"tns:GetCityForecastByZIPSoapOut\" />\r\n        </wsdl:operation>\r\n        <wsdl:operation name=\"GetCityWeatherByZIP\">\r\n            <wsdl:documentation xmlns:wsdl=\"http://schemas.xmlsoap.org/wsdl/\">Allows you to get your City's Weather, which is updated hourly. U.S. Only</wsdl:documentation>\r\n            <wsdl:input message=\"tns:GetCityWeatherByZIPSoapIn\" />\r\n            <wsdl:output message=\"tns:GetCityWeatherByZIPSoapOut\" />\r\n        </wsdl:operation>\r\n    </wsdl:portType>\r\n    <wsdl:portType name=\"WeatherHttpGet\">\r\n        <wsdl:operation name=\"GetWeatherInformation\">\r\n            <wsdl:documentation xmlns:wsdl=\"http://schemas.xmlsoap.org/wsdl/\">Gets Information for each WeatherID</wsdl:documentation>\r\n            <wsdl:input message=\"tns:GetWeatherInformationHttpGetIn\" />\r\n            <wsdl:output message=\"tns:GetWeatherInformationHttpGetOut\" />\r\n        </wsdl:operation>\r\n        <wsdl:operation name=\"GetCityForecastByZIP\">\r\n            <wsdl:documentation xmlns:wsdl=\"http://schemas.xmlsoap.org/wsdl/\">Allows you to get your City Forecast Over the Next 7 Days, which is updated hourly. U.S. Only</wsdl:documentation>\r\n            <wsdl:input message=\"tns:GetCityForecastByZIPHttpGetIn\" />\r\n            <wsdl:output message=\"tns:GetCityForecastByZIPHttpGetOut\" />\r\n        </wsdl:operation>\r\n        <wsdl:operation name=\"GetCityWeatherByZIP\">\r\n            <wsdl:documentation xmlns:wsdl=\"http://schemas.xmlsoap.org/wsdl/\">Allows you to get your City's Weather, which is updated hourly. U.S. Only</wsdl:documentation>\r\n            <wsdl:input message=\"tns:GetCityWeatherByZIPHttpGetIn\" />\r\n            <wsdl:output message=\"tns:GetCityWeatherByZIPHttpGetOut\" />\r\n        </wsdl:operation>\r\n    </wsdl:portType>\r\n    <wsdl:portType name=\"WeatherHttpPost\">\r\n        <wsdl:operation name=\"GetWeatherInformation\">\r\n            <wsdl:documentation xmlns:wsdl=\"http://schemas.xmlsoap.org/wsdl/\">Gets Information for each WeatherID</wsdl:documentation>\r\n            <wsdl:input message=\"tns:GetWeatherInformationHttpPostIn\" />\r\n            <wsdl:output message=\"tns:GetWeatherInformationHttpPostOut\" />\r\n        </wsdl:operation>\r\n        <wsdl:operation name=\"GetCityForecastByZIP\">\r\n            <wsdl:documentation xmlns:wsdl=\"http://schemas.xmlsoap.org/wsdl/\">Allows you to get your City Forecast Over the Next 7 Days, which is updated hourly. U.S. Only</wsdl:documentation>\r\n            <wsdl:input message=\"tns:GetCityForecastByZIPHttpPostIn\" />\r\n            <wsdl:output message=\"tns:GetCityForecastByZIPHttpPostOut\" />\r\n        </wsdl:operation>\r\n        <wsdl:operation name=\"GetCityWeatherByZIP\">\r\n            <wsdl:documentation xmlns:wsdl=\"http://schemas.xmlsoap.org/wsdl/\">Allows you to get your City's Weather, which is updated hourly. U.S. Only</wsdl:documentation>\r\n            <wsdl:input message=\"tns:GetCityWeatherByZIPHttpPostIn\" />\r\n            <wsdl:output message=\"tns:GetCityWeatherByZIPHttpPostOut\" />\r\n        </wsdl:operation>\r\n    </wsdl:portType>\r\n    <wsdl:binding name=\"WeatherSoap\" type=\"tns:WeatherSoap\">\r\n        <soap:binding transport=\"http://schemas.xmlsoap.org/soap/http\" />\r\n        <wsdl:operation name=\"GetWeatherInformation\">\r\n            <soap:operation soapAction=\"http://ws.cdyne.com/WeatherWS/GetWeatherInformation\" style=\"document\" />\r\n            <wsdl:input>\r\n                <soap:body use=\"literal\" />\r\n            </wsdl:input>\r\n            <wsdl:output>\r\n                <soap:body use=\"literal\" />\r\n            </wsdl:output>\r\n        </wsdl:operation>\r\n        <wsdl:operation name=\"GetCityForecastByZIP\">\r\n            <soap:operation soapAction=\"http://ws.cdyne.com/WeatherWS/GetCityForecastByZIP\" style=\"document\" />\r\n            <wsdl:input>\r\n                <soap:body use=\"literal\" />\r\n            </wsdl:input>\r\n            <wsdl:output>\r\n                <soap:body use=\"literal\" />\r\n            </wsdl:output>\r\n        </wsdl:operation>\r\n        <wsdl:operation name=\"GetCityWeatherByZIP\">\r\n            <soap:operation soapAction=\"http://ws.cdyne.com/WeatherWS/GetCityWeatherByZIP\" style=\"document\" />\r\n            <wsdl:input>\r\n                <soap:body use=\"literal\" />\r\n            </wsdl:input>\r\n            <wsdl:output>\r\n                <soap:body use=\"literal\" />\r\n            </wsdl:output>\r\n        </wsdl:operation>\r\n    </wsdl:binding>\r\n    <wsdl:binding name=\"WeatherSoap12\" type=\"tns:WeatherSoap\">\r\n        <soap12:binding transport=\"http://schemas.xmlsoap.org/soap/http\" />\r\n        <wsdl:operation name=\"GetWeatherInformation\">\r\n            <soap12:operation soapAction=\"http://ws.cdyne.com/WeatherWS/GetWeatherInformation\" style=\"document\" />\r\n            <wsdl:input>\r\n                <soap12:body use=\"literal\" />\r\n            </wsdl:input>\r\n            <wsdl:output>\r\n                <soap12:body use=\"literal\" />\r\n            </wsdl:output>\r\n        </wsdl:operation>\r\n        <wsdl:operation name=\"GetCityForecastByZIP\">\r\n            <soap12:operation soapAction=\"http://ws.cdyne.com/WeatherWS/GetCityForecastByZIP\" style=\"document\" />\r\n            <wsdl:input>\r\n                <soap12:body use=\"literal\" />\r\n            </wsdl:input>\r\n            <wsdl:output>\r\n                <soap12:body use=\"literal\" />\r\n            </wsdl:output>\r\n        </wsdl:operation>\r\n        <wsdl:operation name=\"GetCityWeatherByZIP\">\r\n            <soap12:operation soapAction=\"http://ws.cdyne.com/WeatherWS/GetCityWeatherByZIP\" style=\"document\" />\r\n            <wsdl:input>\r\n                <soap12:body use=\"literal\" />\r\n            </wsdl:input>\r\n            <wsdl:output>\r\n                <soap12:body use=\"literal\" />\r\n            </wsdl:output>\r\n        </wsdl:operation>\r\n    </wsdl:binding>\r\n    <wsdl:binding name=\"WeatherHttpGet\" type=\"tns:WeatherHttpGet\">\r\n        <http:binding verb=\"GET\" />\r\n        <wsdl:operation name=\"GetWeatherInformation\">\r\n            <http:operation location=\"/GetWeatherInformation\" />\r\n            <wsdl:input>\r\n                <http:urlEncoded />\r\n            </wsdl:input>\r\n            <wsdl:output>\r\n                <mime:mimeXml part=\"Body\" />\r\n            </wsdl:output>\r\n        </wsdl:operation>\r\n        <wsdl:operation name=\"GetCityForecastByZIP\">\r\n            <http:operation location=\"/GetCityForecastByZIP\" />\r\n            <wsdl:input>\r\n                <http:urlEncoded />\r\n            </wsdl:input>\r\n            <wsdl:output>\r\n                <mime:mimeXml part=\"Body\" />\r\n            </wsdl:output>\r\n        </wsdl:operation>\r\n        <wsdl:operation name=\"GetCityWeatherByZIP\">\r\n            <http:operation location=\"/GetCityWeatherByZIP\" />\r\n            <wsdl:input>\r\n                <http:urlEncoded />\r\n            </wsdl:input>\r\n            <wsdl:output>\r\n                <mime:mimeXml part=\"Body\" />\r\n            </wsdl:output>\r\n        </wsdl:operation>\r\n    </wsdl:binding>\r\n    <wsdl:binding name=\"WeatherHttpPost\" type=\"tns:WeatherHttpPost\">\r\n        <http:binding verb=\"POST\" />\r\n        <wsdl:operation name=\"GetWeatherInformation\">\r\n            <http:operation location=\"/GetWeatherInformation\" />\r\n            <wsdl:input>\r\n                <mime:content type=\"application/x-www-form-urlencoded\" />\r\n            </wsdl:input>\r\n            <wsdl:output>\r\n                <mime:mimeXml part=\"Body\" />\r\n            </wsdl:output>\r\n        </wsdl:operation>\r\n        <wsdl:operation name=\"GetCityForecastByZIP\">\r\n            <http:operation location=\"/GetCityForecastByZIP\" />\r\n            <wsdl:input>\r\n                <mime:content type=\"application/x-www-form-urlencoded\" />\r\n            </wsdl:input>\r\n            <wsdl:output>\r\n                <mime:mimeXml part=\"Body\" />\r\n            </wsdl:output>\r\n        </wsdl:operation>\r\n        <wsdl:operation name=\"GetCityWeatherByZIP\">\r\n            <http:operation location=\"/GetCityWeatherByZIP\" />\r\n            <wsdl:input>\r\n                <mime:content type=\"application/x-www-form-urlencoded\" />\r\n            </wsdl:input>\r\n            <wsdl:output>\r\n                <mime:mimeXml part=\"Body\" />\r\n            </wsdl:output>\r\n        </wsdl:operation>\r\n    </wsdl:binding>\r\n    <wsdl:service name=\"Weather\">\r\n        <wsdl:port name=\"WeatherSoap\" binding=\"tns:WeatherSoap\">\r\n            <soap:address location=\"http://wsf.cdyne.com/WeatherWS/Weather.asmx\" />\r\n        </wsdl:port>\r\n        <wsdl:port name=\"WeatherSoap12\" binding=\"tns:WeatherSoap12\">\r\n            <soap12:address location=\"http://wsf.cdyne.com/WeatherWS/Weather.asmx\" />\r\n        </wsdl:port>\r\n        <wsdl:port name=\"WeatherHttpGet\" binding=\"tns:WeatherHttpGet\">\r\n            <http:address location=\"http://wsf.cdyne.com/WeatherWS/Weather.asmx\" />\r\n        </wsdl:port>\r\n        <wsdl:port name=\"WeatherHttpPost\" binding=\"tns:WeatherHttpPost\">\r\n            <http:address location=\"http://wsf.cdyne.com/WeatherWS/Weather.asmx\" />\r\n        </wsdl:port>\r\n    </wsdl:service>\r\n</wsdl:definitions>\r\n"
  },
  {
    "path": "src/Middleware/CisDhlMiddleware.php",
    "content": "<?php\n\nnamespace CodeDredd\\Soap\\Middleware;\n\nuse Http\\Client\\Common\\Plugin;\nuse Http\\Promise\\Promise;\nuse Psr\\Http\\Message\\RequestInterface;\nuse Psr\\Http\\Message\\ResponseInterface;\nuse Soap\\Psr18Transport\\Xml\\XmlMessageManipulator;\nuse Soap\\Xml\\Builder\\SoapHeader;\nuse Soap\\Xml\\Builder\\SoapHeaders;\nuse Soap\\Xml\\Manipulator\\PrependSoapHeaders;\nuse VeeWee\\Xml\\Dom\\Document;\n\nuse function VeeWee\\Xml\\Dom\\Builder\\children;\nuse function VeeWee\\Xml\\Dom\\Builder\\namespaced_element;\nuse function VeeWee\\Xml\\Dom\\Builder\\value;\n\nclass CisDhlMiddleware implements Plugin\n{\n    /**\n     * @var string\n     */\n    public const CIS_NS = 'http://dhl.de/webservice/cisbase';\n\n    /**\n     * @var string\n     */\n    private $user;\n\n    /**\n     * @var string\n     */\n    private $signature;\n\n    public function __construct(string $user, string $signature)\n    {\n        $this->user = $user;\n        $this->signature = $signature;\n    }\n\n    public function getName(): string\n    {\n        return 'cis_dhl_middleware';\n    }\n\n    public function handleRequest(RequestInterface $request, callable $next, callable $first): Promise\n    {\n        return $next(\n            (new XmlMessageManipulator())(\n                $request,\n                function (Document $document) {\n                    $builder = new SoapHeaders(\n                        new SoapHeader(\n                            self::CIS_NS,\n                            'cis:Authentification',\n                            children(\n                                namespaced_element(self::CIS_NS, 'user', value($this->user)),\n                                namespaced_element(self::CIS_NS, 'signature', value($this->signature))\n                            )\n                        )\n                    );\n\n                    $headers = $document->build($builder);\n\n                    return $document->manipulate(new PrependSoapHeaders(...$headers));\n                }\n            )\n        );\n    }\n\n    /**\n     * @param  ResponseInterface  $response\n     * @return ResponseInterface\n     */\n    public function afterResponse(ResponseInterface $response): ResponseInterface\n    {\n        return $response;\n    }\n}\n"
  },
  {
    "path": "src/Middleware/WsseMiddleware.php",
    "content": "<?php\n\nnamespace CodeDredd\\Soap\\Middleware;\n\nuse Http\\Client\\Common\\Plugin;\nuse Http\\Promise\\Promise;\nuse Psr\\Http\\Message\\RequestInterface;\nuse Psr\\Http\\Message\\ResponseInterface;\nuse RobRichards\\WsePhp\\WSSESoap;\nuse RobRichards\\XMLSecLibs\\XMLSecurityKey;\nuse Soap\\Psr18Transport\\Xml\\XmlMessageManipulator;\nuse VeeWee\\Xml\\Dom\\Document;\n\nclass WsseMiddleware implements Plugin\n{\n    private string $privateKeyFile;\n    private string $publicKeyFile;\n    private string $serverCertificateFile = '';\n    private int $timestamp = 3600;\n    private bool $signAllHeaders = false;\n    private string $digitalSignMethod = XMLSecurityKey::RSA_SHA1;\n    private string $userTokenName = '';\n    private string $userTokenPassword = '';\n    private bool $userTokenDigest = false;\n    private bool $encrypt = false;\n    private bool $hasUserToken = false;\n    private bool $serverCertificateHasSubjectKeyIdentifier = true;\n    private bool $mustUnderstand = true;\n\n    public function __construct(array $properties)\n    {\n        foreach ($properties as $key => $value) {\n            $this->{$key} = $value;\n        }\n    }\n\n    public function getName(): string\n    {\n        return 'wsse_middleware';\n    }\n\n    public function withTimestamp(int $timestamp = 3600): self\n    {\n        $this->timestamp = $timestamp;\n\n        return $this;\n    }\n\n    public function withAllHeadersSigned(): self\n    {\n        $this->signAllHeaders = true;\n\n        return $this;\n    }\n\n    public function withDigitalSignMethod(string $digitalSignMethod): self\n    {\n        $this->digitalSignMethod = $digitalSignMethod;\n\n        return $this;\n    }\n\n    public function withUserToken(string $username, string $password = null, $digest = false): self\n    {\n        $this->userTokenName = $username;\n        $this->userTokenPassword = $password;\n        $this->userTokenDigest = $digest;\n\n        return $this;\n    }\n\n    public function withEncryption(string $serverCertificateFile): self\n    {\n        $this->encrypt = true;\n        $this->serverCertificateFile = $serverCertificateFile;\n\n        return $this;\n    }\n\n    public function withServerCertificateHasSubjectKeyIdentifier(bool $hasSubjectKeyIdentifier): self\n    {\n        $this->serverCertificateHasSubjectKeyIdentifier = $hasSubjectKeyIdentifier;\n\n        return $this;\n    }\n\n    public function handleRequest(RequestInterface $request, callable $next, callable $first): Promise\n    {\n        return $this->beforeRequest($next, $request)->then(\n            fn (ResponseInterface $response): ResponseInterface => $this->afterResponse($response)\n        );\n    }\n\n    public function beforeRequest(callable $handler, RequestInterface $request): Promise\n    {\n        $request = (new XmlMessageManipulator())(\n            $request,\n            function (Document $xml) {\n                $wsse = new WSSESoap($xml->toUnsafeDocument(), $this->mustUnderstand);\n\n                // Prepare the WSSE soap class:\n                $wsse->signAllHeaders = $this->signAllHeaders;\n                $wsse->addTimestamp($this->timestamp);\n\n                // Add a user token if this is configured.\n                if ($this->hasUserToken) {\n                    $wsse->addUserToken($this->userTokenName, $this->userTokenPassword, $this->userTokenDigest);\n                }\n\n                if (! empty($this->privateKeyFile) && ! empty($this->publicKeyFile)) {\n                    //  Add certificate (BinarySecurityToken) to the message\n                    $token = $wsse->addBinaryToken(file_get_contents($this->publicKeyFile));\n\n                    // Create new XMLSec Key using the dsigType and type is private key\n                    $key = new XMLSecurityKey($this->digitalSignMethod, ['type' => 'private']);\n                    $key->loadKey($this->privateKeyFile, true);\n                    $wsse->signSoapDoc($key);\n\n                    //  Attach token pointer to Signature:\n                    $wsse->attachTokentoSig($token);\n                }\n\n                // Add end-to-end encryption if configured:\n                if ($this->encrypt) {\n                    $key = new XMLSecurityKey(XMLSecurityKey::AES256_CBC);\n                    $key->generateSessionKey();\n                    $siteKey = new XMLSecurityKey(XMLSecurityKey::RSA_OAEP_MGF1P, ['type' => 'public']);\n                    $siteKey->loadKey($this->serverCertificateFile, true, true);\n                    $wsse->encryptSoapDoc($siteKey, $key, [\n                        'KeyInfo' => [\n                            'X509SubjectKeyIdentifier' => $this->serverCertificateHasSubjectKeyIdentifier,\n                        ],\n                    ]);\n                }\n            }\n        );\n\n        return $handler($request);\n    }\n\n    public function afterResponse(ResponseInterface $response): ResponseInterface\n    {\n        if (! $this->encrypt) {\n            return $response;\n        }\n\n        return (new XmlMessageManipulator())(\n            $response,\n            function (Document $xml) {\n                $wsse = new WSSESoap($xml->toUnsafeDocument());\n                $wsse->decryptSoapDoc(\n                    $xml->toUnsafeDocument(),\n                    [\n                        'keys' => [\n                            'private' => [\n                                'key' => $this->privateKeyFile,\n                                'isFile' => true,\n                                'isCert' => false,\n                            ],\n                        ],\n                    ]\n                );\n            }\n        );\n    }\n}\n"
  },
  {
    "path": "src/Ray/LaravelRay.php",
    "content": "<?php\n\nnamespace CodeDredd\\Soap\\Ray;\n\nuse Closure;\nuse Spatie\\LaravelRay\\RayProxy;\nuse Spatie\\LaravelRay\\Watchers\\Watcher;\nuse Spatie\\Ray\\Ray as SpatieRay;\n\nclass LaravelRay\n{\n    public function register()\n    {\n        SpatieRay::macro('showSoapClientRequests', function ($callable = null): RayProxy {\n            $watcher = app(SoapClientWatcher::class);\n\n            return $this->handleWatcherCallable($watcher, $callable);\n        });\n        SpatieRay::macro('stopShowingSoapClientRequests', fn () => app(SoapClientWatcher::class)->disable());\n    }\n\n    protected function handleWatcherCallable(Watcher $watcher, Closure $callable = null): RayProxy\n    {\n        $rayProxy = new RayProxy();\n\n        $wasEnabled = $watcher->enabled();\n\n        $watcher->enable();\n\n        $watcher->setRayProxy($rayProxy);\n\n        if ($callable) {\n            $callable();\n\n            if (! $wasEnabled) {\n                $watcher->disable();\n            }\n        }\n\n        return $rayProxy;\n    }\n}\n"
  },
  {
    "path": "src/Ray/SoapClientWatcher.php",
    "content": "<?php\n\nnamespace CodeDredd\\Soap\\Ray;\n\nuse CodeDredd\\Soap\\Client\\Events\\RequestSending;\nuse CodeDredd\\Soap\\Client\\Events\\ResponseReceived;\nuse CodeDredd\\Soap\\Client\\Request;\nuse CodeDredd\\Soap\\Client\\Response;\nuse Illuminate\\Support\\Facades\\Event;\nuse Spatie\\LaravelRay\\Ray;\nuse Spatie\\LaravelRay\\Watchers\\Watcher;\nuse Spatie\\Ray\\Payloads\\TablePayload;\n\nclass SoapClientWatcher extends Watcher\n{\n    public function register(): void\n    {\n        $this->enabled = config('soap.ray.send_soap_client_requests', false);\n\n        Event::listen(RequestSending::class, function (RequestSending $event) {\n            if (! $this->enabled()) {\n                return;\n            }\n\n            $ray = $this->handleRequest($event->request);\n\n            optional($this->rayProxy)->applyCalledMethods($ray);\n        });\n\n        Event::listen(ResponseReceived::class, function (ResponseReceived $event) {\n            if (! $this->enabled()) {\n                return;\n            }\n\n            $ray = $this->handleResponse($event->request, $event->response);\n\n            optional($this->rayProxy)->applyCalledMethods($ray);\n        });\n    }\n\n    protected function handleRequest(Request $request)\n    {\n        $payload = new TablePayload([\n            'Action' => $request->action(),\n            'URL' => $request->url(),\n            'Headers' => $request->headers(),\n            'Data' => $request->arguments(),\n            'Body' => $request->body(),\n        ], 'SOAP');\n\n        return app(Ray::class)->sendRequest($payload);\n    }\n\n    protected function handleResponse(Request $request, Response $response)\n    {\n        $payload = new TablePayload([\n            'URL' => $request->url(),\n            'Real Request' => ! empty($response->handlerStats()),\n            'Success' => $response->successful(),\n            'Status' => $response->status(),\n            'Headers' => $response->headers(),\n            'Body' => rescue(function () use ($response) {\n                return $response->json();\n            }, $response->body(), false),\n            'Size' => $response->handlerStats()['size_download'] ?? null,\n            'Connection time' => $response->handlerStats()['connect_time'] ?? null,\n            'Duration' => $response->handlerStats()['total_time'] ?? null,\n            'Request Size' => $response->handlerStats()['request_size'] ?? null,\n        ], 'SOAP');\n\n        return app(Ray::class)->sendRequest($payload);\n    }\n}\n"
  },
  {
    "path": "src/SoapClient.php",
    "content": "<?php\n\nnamespace CodeDredd\\Soap;\n\nuse Closure;\nuse CodeDredd\\Soap\\Client\\Events\\ConnectionFailed;\nuse CodeDredd\\Soap\\Client\\Events\\RequestSending;\nuse CodeDredd\\Soap\\Client\\Events\\ResponseReceived;\nuse CodeDredd\\Soap\\Client\\Request;\nuse CodeDredd\\Soap\\Client\\Response;\nuse CodeDredd\\Soap\\Driver\\ExtSoap\\ExtSoapEngineFactory;\nuse CodeDredd\\Soap\\Exceptions\\NotFoundConfigurationException;\nuse CodeDredd\\Soap\\Exceptions\\SoapException;\nuse CodeDredd\\Soap\\Middleware\\CisDhlMiddleware;\nuse CodeDredd\\Soap\\Middleware\\WsseMiddleware;\nuse GuzzleHttp\\Client;\nuse GuzzleHttp\\HandlerStack;\nuse GuzzleHttp\\Psr7\\Response as Psr7Response;\nuse GuzzleHttp\\TransferStats;\nuse Http\\Client\\Common\\PluginClient;\nuse Http\\Client\\Exception\\HttpException;\nuse Illuminate\\Contracts\\Validation\\Validator;\nuse Illuminate\\Support\\Arr;\nuse Illuminate\\Support\\Str;\nuse Illuminate\\Support\\Traits\\Conditionable;\nuse Illuminate\\Support\\Traits\\Macroable;\nuse Phpro\\SoapClient\\Type\\ResultInterface;\nuse Phpro\\SoapClient\\Type\\ResultProviderInterface;\nuse Psr\\Http\\Client\\ClientInterface;\nuse Psr\\Http\\Message\\RequestInterface;\nuse Soap\\Engine\\Engine;\nuse Soap\\Engine\\Transport;\nuse Soap\\ExtSoapEngine\\AbusedClient;\nuse Soap\\ExtSoapEngine\\ExtSoapOptions;\nuse Soap\\ExtSoapEngine\\Transport\\TraceableTransport;\nuse Soap\\ExtSoapEngine\\Wsdl\\WsdlProvider;\nuse Soap\\Psr18Transport\\Middleware\\RemoveEmptyNodesMiddleware;\nuse Soap\\Psr18Transport\\Psr18Transport;\nuse Soap\\Psr18Transport\\Wsdl\\Psr18Loader;\nuse Soap\\Psr18WsseMiddleware\\WsaMiddleware;\nuse Soap\\Psr18WsseMiddleware\\WsaMiddleware2005;\nuse Soap\\Wsdl\\Loader\\FlatteningLoader;\nuse Soap\\Wsdl\\Loader\\StreamWrapperLoader;\n\n/**\n * Class SoapClient.\n */\nclass SoapClient\n{\n    use Macroable {\n        __call as macroCall;\n    }\n    use Conditionable;\n\n    protected ClientInterface $client;\n\n    protected PluginClient $pluginClient;\n\n    protected Engine $engine;\n\n    protected array $options = [];\n\n    protected ExtSoapOptions $extSoapOptions;\n\n    protected TraceableTransport|Transport $transport;\n\n    protected array $guzzleClientOptions = [];\n\n    /**\n     * The transfer stats for the request.\n     */\n    protected ?TransferStats $transferStats = null;\n\n    protected string $wsdl = '';\n\n    protected bool $isClientBuilded = false;\n\n    protected array $middlewares = [];\n\n    protected SoapFactory|null $factory;\n\n    protected FlatteningLoader|WsdlProvider $wsdlProvider;\n\n    protected array $cookies = [];\n\n    /**\n     * The callbacks that should execute before the request is sent.\n     */\n    protected \\Illuminate\\Support\\Collection $beforeSendingCallbacks;\n\n    /**\n     * The stub callables that will handle requests.\n     */\n    protected \\Illuminate\\Support\\Collection|null $stubCallbacks;\n\n    /**\n     * The sent request object, if a request has been made.\n     *\n     * @var Request|null\n     */\n    protected $request;\n\n    /**\n     * Create a new Soap Client instance.\n     *\n     * @param  \\CodeDredd\\Soap\\SoapFactory|null  $factory\n     * @return void\n     */\n    public function __construct(SoapFactory $factory = null)\n    {\n        $this->factory = $factory;\n        $this->client = new Client($this->guzzleClientOptions);\n        $this->pluginClient = new PluginClient($this->client, $this->middlewares);\n        $this->wsdlProvider = new FlatteningLoader(Psr18Loader::createForClient($this->pluginClient));\n        $this->beforeSendingCallbacks = collect([function (Request $request, array $options, SoapClient $soapClient) {\n            $soapClient->request = $request;\n            $soapClient->cookies = Arr::wrap($options['cookies']);\n\n            $soapClient->dispatchRequestSendingEvent();\n        }]);\n    }\n\n    public function refreshWsdlProvider()\n    {\n        $this->wsdlProvider = new FlatteningLoader(Psr18Loader::createForClient($this->pluginClient));\n\n        return $this;\n    }\n\n    public function refreshPluginClient(): static\n    {\n        $this->pluginClient = new PluginClient($this->client, $this->middlewares);\n\n        return $this;\n    }\n\n    public function getPluginClient(): PluginClient\n    {\n        return $this->pluginClient;\n    }\n\n    protected function setTransport(Transport $handler = null): static\n    {\n        $soapClient = AbusedClient::createFromOptions(\n            ExtSoapOptions::defaults($this->wsdl, $this->options)\n        );\n        $transport = $handler ?? Psr18Transport::createForClient($this->pluginClient);\n\n        $this->transport = $handler ?? new TraceableTransport(\n            $soapClient,\n            $transport\n        );\n\n        return $this;\n    }\n\n    /**\n     * Add the given headers to the request.\n     */\n    public function withHeaders(array $headers): static\n    {\n        return $this->withGuzzleClientOptions(array_merge_recursive($this->options, [\n            'headers' => $headers,\n        ]));\n    }\n\n    public function getTransport(): TraceableTransport|Transport\n    {\n        return $this->transport;\n    }\n\n    public function getClient(): Client|ClientInterface\n    {\n        return $this->client;\n    }\n\n    public function withGuzzleClientOptions(array ...$options): static\n    {\n        $this->guzzleClientOptions = array_merge_recursive($this->guzzleClientOptions, ...$options);\n        $this->client = new Client($this->guzzleClientOptions);\n\n        return $this;\n    }\n\n    public function getEngine(): Engine\n    {\n        return $this->engine;\n    }\n\n    /**\n     * @return $this\n     */\n    public function withRemoveEmptyNodes()\n    {\n        $this->middlewares = array_merge_recursive($this->middlewares, [\n            new RemoveEmptyNodesMiddleware(),\n        ]);\n\n        return $this;\n    }\n\n    /**\n     * @param  string|array  $username\n     * @param  string|null  $password\n     * @return $this\n     */\n    public function withBasicAuth($username, ?string $password = null)\n    {\n        if (is_array($username)) {\n            ['username' => $username, 'password' => $password] = $username;\n        }\n\n        $this->withHeaders([\n            'Authorization' => sprintf('Basic %s', base64_encode(\n                sprintf('%s:%s', $username, $password)\n            )),\n        ]);\n\n        return $this;\n    }\n\n    /**\n     * @param  string|array  $user\n     * @param  string|null  $signature\n     * @return $this\n     */\n    public function withCisDHLAuth($user, ?string $signature = null)\n    {\n        if (is_array($user)) {\n            ['username' => $user, 'password' => $signature] = $user;\n        }\n\n        $this->middlewares = array_merge_recursive($this->middlewares, [\n            new CisDhlMiddleware($user, $signature),\n        ]);\n\n        return $this;\n    }\n\n    /**\n     * @return $this\n     */\n    public function withWsa()\n    {\n        $this->middlewares = array_merge_recursive($this->middlewares, [\n            new WsaMiddleware(),\n        ]);\n\n        return $this;\n    }\n\n    /**\n     * @return $this\n     */\n    public function withWsa2005()\n    {\n        $this->middlewares = array_merge_recursive($this->middlewares, [\n            new WsaMiddleware2005(),\n        ]);\n\n        return $this;\n    }\n\n    public function withWsse(array $options): static\n    {\n        $this->middlewares = array_merge_recursive($this->middlewares, [\n            new WsseMiddleware($options),\n        ]);\n\n        return $this;\n    }\n\n    /**\n     * Merge new options into the client.\n     *\n     * @param  array  $options\n     * @return $this\n     */\n    public function withOptions(array $options)\n    {\n        return tap($this, function ($request) use ($options) {\n            return $this->options = array_merge_recursive($this->options, $options);\n        });\n    }\n\n    /**\n     * Merge the given options with the current request options.\n     *\n     * @param  array  $options\n     * @return array\n     */\n    public function mergeOptions(...$options)\n    {\n        return array_merge_recursive($this->options, ...$options);\n    }\n\n    /**\n     * Make it possible to debug the last request.\n     */\n    public function debugLastSoapRequest(): array\n    {\n        if ($this->transport instanceof TraceableTransport) {\n            $lastRequestInfo = $this->transport->collectLastRequestInfo();\n\n            return [\n                'request' => [\n                    'headers' => trim($lastRequestInfo->getLastRequestHeaders()),\n                    'body' => $lastRequestInfo->getLastRequest(),\n                ],\n                'response' => [\n                    'headers' => trim($lastRequestInfo->getLastResponseHeaders()),\n                    'body' => $lastRequestInfo->getLastResponse(),\n                ],\n            ];\n        }\n\n        return [];\n    }\n\n    /**\n     * Handle a failed validation attempt.\n     *\n     * @param  \\Illuminate\\Contracts\\Validation\\Validator  $validator\n     * @return Response\n     */\n    protected function failedValidation(Validator $validator)\n    {\n        return Response::fromSoapResponse([\n            'success' => false,\n            'message' => __('Invalid data.'),\n            'errors' => $validator->errors(),\n        ]);\n    }\n\n    public function __call($method, $parameters)\n    {\n        if (static::hasMacro($method)) {\n            return $this->macroCall($method, $parameters);\n        }\n\n        return $this->call($method, $parameters[0] ?? $parameters);\n    }\n\n    public function call(string $method, Validator|array $arguments = []): Response\n    {\n        try {\n            if (! $this->isClientBuilded) {\n                $this->buildClient();\n            }\n            $this->refreshEngine();\n            if ($arguments instanceof Validator) {\n                if ($arguments->fails()) {\n                    return $this->failedValidation($arguments);\n                }\n                $arguments = $arguments->validated();\n            }\n            $arguments = config()->get('soap.call.wrap_arguments_in_array', true) ? [$arguments] : $arguments;\n            $result = $this->engine->request($method, $arguments);\n            if ($result instanceof ResultProviderInterface) {\n                return $this->buildResponse(Response::fromSoapResponse($result->getResult()));\n            }\n            if (! $result instanceof ResultInterface) {\n                return $this->buildResponse(Response::fromSoapResponse($result));\n            }\n\n            return $this->buildResponse(new Response(new Psr7Response(200, [], $result)));\n        } catch (\\Exception $exception) {\n            if ($exception instanceof \\SoapFault) {\n                return $this->buildResponse(Response::fromSoapFault($exception));\n            }\n            $previous = $exception->getPrevious();\n            $this->dispatchConnectionFailedEvent();\n            if ($previous instanceof HttpException) {\n                /** @var HttpException $previous */\n                return new Response($previous->getResponse());\n            }\n\n            throw SoapException::fromThrowable($exception);\n        }\n    }\n\n    protected function buildResponse($response)\n    {\n        return tap($response, function ($result) {\n            $this->populateResponse($result);\n            $this->dispatchResponseReceivedEvent($result);\n        });\n    }\n\n    /**\n     * Build the Soap client.\n     *\n     * @param  string  $setup\n     * @return SoapClient\n     *\n     * @throws NotFoundConfigurationException\n     */\n    public function buildClient(string $setup = '')\n    {\n        $this->byConfig($setup);\n        $this->withGuzzleClientOptions([\n            'handler' => $this->buildHandlerStack(),\n            'on_stats' => function ($transferStats) {\n                $this->transferStats = $transferStats;\n            },\n        ]);\n        $this->isClientBuilded = true;\n\n        return $this;\n    }\n\n    /**\n     * @param  string  $setup\n     * @return $this\n     *\n     * @throws NotFoundConfigurationException\n     */\n    public function byConfig(string $setup)\n    {\n        if (! empty($setup)) {\n            $setup = config()->get('soap.clients.'.$setup);\n            if (! $setup) {\n                throw new NotFoundConfigurationException($setup);\n            }\n            foreach ($setup as $setupItem => $setupItemConfig) {\n                if (is_bool($setupItemConfig)) {\n                    $this->{Str::camel($setupItem)}();\n                } elseif (is_array($setupItemConfig)) {\n                    $this->{Str::camel($setupItem)}($this->arrayKeysToCamel($setupItemConfig));\n                } elseif (is_string($setupItemConfig)) {\n                    $this->{Str::camel($setupItem)}($setupItemConfig);\n                }\n            }\n        }\n\n        return $this;\n    }\n\n    /**\n     * @param  array  $items\n     * @return array\n     */\n    protected function arrayKeysToCamel(array $items)\n    {\n        $changedItems = [];\n        foreach ($items as $key => $value) {\n            $changedItems[Str::camel($key)] = $value;\n        }\n\n        return $changedItems;\n    }\n\n    /**\n     * Build the before sending handler stack.\n     *\n     * @return \\GuzzleHttp\\HandlerStack\n     */\n    public function buildHandlerStack()\n    {\n        return tap(HandlerStack::create(), function ($stack) {\n            $stack->push($this->buildBeforeSendingHandler(), 'before_sending');\n            $stack->push($this->buildRecorderHandler(), 'recorder');\n            $stack->push($this->buildStubHandler(), 'stub');\n        });\n    }\n\n    /**\n     * Build the before sending handler.\n     */\n    public function buildBeforeSendingHandler(): Closure\n    {\n        return function ($handler) {\n            return function ($request, $options) use ($handler) {\n                return $handler($this->runBeforeSendingCallbacks($request, $options), $options);\n            };\n        };\n    }\n\n    /**\n     * Execute the \"before sending\" callbacks.\n     */\n    public function runBeforeSendingCallbacks(RequestInterface $request, array $options): mixed\n    {\n        return tap($request, function ($request) use ($options) {\n            $this->beforeSendingCallbacks->each->__invoke(\n                new Request($request),\n                $options,\n                $this\n            );\n        });\n    }\n\n    /**\n     * Populate the given response with additional data.\n     *\n     * @param  \\CodeDredd\\Soap\\Client\\Response  $response\n     * @return \\CodeDredd\\Soap\\Client\\Response\n     */\n    protected function populateResponse(Response $response)\n    {\n        $response->setCookies($this->cookies);\n        $response->setTransferStats($this->transferStats);\n\n        return $response;\n    }\n\n    /**\n     * Dispatch the RequestSending event if a dispatcher is available.\n     *\n     * @return void\n     */\n    protected function dispatchRequestSendingEvent()\n    {\n        event(new RequestSending($this->request));\n    }\n\n    /**\n     * Dispatch the ResponseReceived event if a dispatcher is available.\n     *\n     * @param  \\CodeDredd\\Soap\\Client\\Response  $response\n     * @return void\n     */\n    protected function dispatchResponseReceivedEvent(Response $response)\n    {\n        if (! $this->request) {\n            return;\n        }\n\n        event(new ResponseReceived($this->request, $response));\n    }\n\n    /**\n     * Dispatch the ConnectionFailed event if a dispatcher is available.\n     *\n     * @return void\n     */\n    protected function dispatchConnectionFailedEvent()\n    {\n        event(new ConnectionFailed($this->request));\n    }\n\n    /**\n     * Build the recorder handler.\n     *\n     * @return Closure\n     */\n    public function buildRecorderHandler()\n    {\n        return function ($handler) {\n            return function ($request, $options) use ($handler) {\n                $promise = $handler($request, $options);\n\n                return $promise->then(function ($response) use ($request) {\n                    optional($this->factory)->recordRequestResponsePair(\n                        new Request($request),\n                        new Response($response)\n                    );\n\n                    return $response;\n                });\n            };\n        };\n    }\n\n    /**\n     * Build the stub handler.\n     *\n     * @return Closure\n     */\n    public function buildStubHandler()\n    {\n        return function (callable $handler) {\n            return function ($request, $options) use ($handler) {\n                $response = ($this->stubCallbacks ?? collect())\n                    ->map\n                    ->__invoke(new Request($request), $options)\n                    ->filter()\n                    ->first();\n                if (is_null($response)) {\n                    return $handler($request, $options);\n                } elseif (is_array($response)) {\n                    return SoapFactory::response($response);\n                }\n\n                return $response;\n            };\n        };\n    }\n\n    /**\n     * @return $this\n     */\n    protected function refreshEngine()\n    {\n        $this->refreshPluginClient();\n        $this->setTransport();\n        $this->refreshExtSoapOptions();\n        $this->engine = ExtSoapEngineFactory::fromOptionsWithHandler(\n            $this->extSoapOptions,\n            $this->transport,\n            $this->factory->isRecording()\n        );\n        $this->refreshWsdlProvider();\n\n        return $this;\n    }\n\n    protected function refreshExtSoapOptions()\n    {\n        $this->extSoapOptions = ExtSoapOptions::defaults($this->wsdl, $this->options);\n        if ($this->factory->isRecording()) {\n            $this->wsdlProvider = new FlatteningLoader(new StreamWrapperLoader());\n//            $this->extSoapOptions->withWsdlProvider($this->wsdlProvider);\n        }\n    }\n\n    /**\n     * @param  string  $wsdl\n     * @return $this\n     */\n    public function baseWsdl(string $wsdl)\n    {\n        $this->wsdl = $wsdl;\n\n        return $this;\n    }\n\n    /**\n     * Register a stub callable that will intercept requests and be able to return stub responses.\n     *\n     * @param  callable  $callback\n     * @return $this\n     */\n    public function stub($callback)\n    {\n        $this->stubCallbacks = collect($callback);\n\n        return $this;\n    }\n}\n"
  },
  {
    "path": "src/SoapFactory.php",
    "content": "<?php\n\nnamespace CodeDredd\\Soap;\n\nuse Closure;\nuse CodeDredd\\Soap\\Client\\ResponseSequence;\nuse GuzzleHttp\\Promise\\Create;\nuse GuzzleHttp\\Psr7\\Response as Psr7Response;\nuse Illuminate\\Support\\Str;\nuse Illuminate\\Support\\Traits\\Macroable;\n\nclass SoapFactory\n{\n    use Macroable {\n        __call as macroCall;\n    }\n\n    /**\n     * The client class name.\n     *\n     * @var string\n     */\n    public static $clientClass = 'CodeDredd\\Soap\\SoapClient';\n\n    /**\n     * The stub callables that will handle requests.\n     *\n     * @var \\Illuminate\\Support\\Collection\n     */\n    protected $stubCallbacks;\n\n    /**\n     * Indicates if the factory is recording requests and responses.\n     *\n     * @var bool\n     */\n    protected $recording = false;\n\n    /**\n     * The recorded response array.\n     *\n     * @var array\n     */\n    protected $recorded = [];\n\n    /**\n     * All created response sequences.\n     *\n     * @var array\n     */\n    protected $responseSequences = [];\n\n    protected $fakeWsdlLocation;\n\n    /**\n     * Create a new factory instance.\n     *\n     * @return void\n     */\n    public function __construct()\n    {\n        $this->stubCallbacks = collect();\n//        $this->fakeWsdlLocation = __DIR__.'/Faker/fake.wsdl';\n    }\n\n    /**\n     * Execute a method against a new pending request instance.\n     *\n     * @param  string  $method\n     * @param  array  $parameters\n     * @return mixed\n     */\n    public function __call($method, $parameters)\n    {\n        if (static::hasMacro($method)) {\n            return $this->macroCall($method, $parameters);\n        }\n\n        if (Str::contains($method, 'assert')) {\n            return (new SoapTesting($this))->{$method}(...$parameters);\n        }\n\n        return tap($this->client(), function ($request) {\n            $request->stub($this->stubCallbacks);\n        })->{$method}(...$parameters);\n    }\n\n    public function isRecording()\n    {\n        return $this->recording;\n    }\n\n    public function getResponseSequences()\n    {\n        return $this->responseSequences;\n    }\n\n    public function getRecorded()\n    {\n        return $this->recorded;\n    }\n\n    /**\n     * Record a request response pair.\n     *\n     * @param  \\CodeDredd\\Soap\\Client\\Request  $request\n     * @param  \\CodeDredd\\Soap\\Client\\Response  $response\n     * @return void\n     */\n    public function recordRequestResponsePair($request, $response)\n    {\n        if ($this->recording) {\n            $this->recorded[] = [$request, $response];\n        }\n    }\n\n    public function fakeWsdl(string $wsdl)\n    {\n        $this->fakeWsdlLocation = $wsdl;\n\n        return $this;\n    }\n\n    public function getFakeWsdl()\n    {\n        return $this->fakeWsdlLocation;\n    }\n\n    /**\n     * Register a response sequence for the given URL pattern.\n     *\n     * @param  string  $url\n     * @return \\CodeDredd\\Soap\\Client\\ResponseSequence\n     */\n    public function fakeSequence($url = '*')\n    {\n        return tap($this->sequence(), function ($sequence) use ($url) {\n            $this->fake([$url => $sequence]);\n        });\n    }\n\n    /**\n     * Get an invokable object that returns a sequence of responses in order for use during stubbing.\n     *\n     * @param  array  $responses\n     * @return \\CodeDredd\\Soap\\Client\\ResponseSequence\n     */\n    public function sequence(array $responses = [])\n    {\n        return $this->responseSequences[] = new ResponseSequence($responses);\n    }\n\n    /**\n     * Register a stub callable that will intercept requests and be able to return stub responses.\n     *\n     * @param  callable|array  $callback\n     * @return $this\n     */\n    public function fake($callback = null)\n    {\n        $this->record();\n\n        if (is_null($callback)) {\n            $callback = function () {\n                return static::response();\n            };\n        }\n\n        if (is_array($callback)) {\n            $callback['*'] = $callback['*'] ?? self::response();\n            foreach ($callback as $method => $callable) {\n                $this->stubMethod($method, $callable);\n            }\n\n            return $this;\n        }\n        $this->stubCallbacks = $this->stubCallbacks->merge(collect([\n            $callback instanceof Closure\n                ? $callback\n                : function () use ($callback) {\n                    return $callback;\n                },\n        ]));\n\n        return $this;\n    }\n\n    /**\n     * Begin recording request / response pairs.\n     *\n     * @return $this\n     */\n    protected function record()\n    {\n        $this->recording = true;\n\n        return $this;\n    }\n\n    /**\n     * Create a new response instance for use during stubbing.\n     *\n     * @param  array|string|null  $body\n     * @param  int  $status\n     * @param  array  $headers\n     * @return \\GuzzleHttp\\Promise\\PromiseInterface\n     */\n    public static function response($body = null, $status = 200, $headers = [])\n    {\n        if (is_array($body)) {\n            $body = json_encode($body);\n        } elseif (is_string($body)) {\n            $body = json_encode([\n                'response' => $body,\n            ]);\n        }\n\n        return Create::promiseFor(new Psr7Response($status, $headers, $body));\n    }\n\n    /**\n     * Stub the given URL using the given callback.\n     *\n     * @param  string  $method\n     * @param  \\CodeDredd\\Soap\\Client\\Response|\\GuzzleHttp\\Promise\\PromiseInterface|callable  $callback\n     * @return $this\n     */\n    public function stubMethod($method, $callback)\n    {\n        return $this->fake(function ($request, $options) use ($method, $callback) {\n            if (! Str::is(Str::start($method, '*'), $request->action())) {\n                return;\n            }\n\n            return $callback instanceof Closure || $callback instanceof ResponseSequence\n                ? $callback($request, $options)\n                : $callback;\n        });\n    }\n\n    /**\n     * Get a collection of the request / response pairs matching the given truth test.\n     *\n     * @param  callable  $callback\n     * @return \\Illuminate\\Support\\Collection\n     */\n    public function recorded($callback)\n    {\n        if (empty($this->recorded)) {\n            return collect();\n        }\n\n        $callback = $callback ?: function () {\n            return true;\n        };\n\n        return collect($this->recorded)->filter(function ($pair) use ($callback) {\n            return $callback($pair[0], $pair[1]);\n        });\n    }\n\n    /**\n     * Get a new client class instance.\n     *\n     * @return SoapClient\n     */\n    public function client()\n    {\n        return new static::$clientClass($this);\n    }\n\n    /**\n     * Set the client class name.\n     *\n     * @param  string  $clientClass\n     */\n    public static function useClientClass(string $clientClass): void\n    {\n        static::$clientClass = $clientClass;\n    }\n}\n"
  },
  {
    "path": "src/SoapServiceProvider.php",
    "content": "<?php\n\nnamespace CodeDredd\\Soap;\n\nuse CodeDredd\\Soap\\Ray\\LaravelRay;\nuse CodeDredd\\Soap\\Ray\\SoapClientWatcher;\nuse Spatie\\LaravelPackageTools\\Package;\nuse Spatie\\LaravelPackageTools\\PackageServiceProvider;\nuse Spatie\\LaravelRay\\Watchers\\Watcher;\n\nclass SoapServiceProvider extends PackageServiceProvider\n{\n    public function configurePackage(Package $package): void\n    {\n        /*\n         * This class is a Package Service Provider\n         *\n         * More info: https://github.com/spatie/laravel-package-tools\n         */\n        $package\n            ->name('soap')\n            ->hasConfigFile('soap');\n    }\n\n    public function packageRegistered()\n    {\n        $this->registerService();\n        $this->registerRay();\n    }\n\n    public function packageBooted()\n    {\n        $this->bootRay();\n    }\n\n    /**\n     * Register Soap's services in the container.\n     *\n     * @return void\n     */\n    protected function registerService()\n    {\n        $this->app->bind('Soap', function () {\n            return new SoapFactory();\n        });\n    }\n\n    protected function registerRay()\n    {\n        if (! class_exists('Spatie\\\\LaravelRay\\\\Ray')) {\n            return;\n        }\n        /** @var LaravelRay $macros */\n        $macros = app(LaravelRay::class);\n\n        $macros->register();\n\n        $this->app->singleton(SoapClientWatcher::class);\n    }\n\n    protected function bootRay()\n    {\n        if (! class_exists('Spatie\\\\LaravelRay\\\\Ray')) {\n            return;\n        }\n\n        /** @var Watcher $watcher */\n        $watcher = app(SoapClientWatcher::class);\n\n        $watcher->register();\n    }\n}\n"
  },
  {
    "path": "src/SoapTesting.php",
    "content": "<?php\n\nnamespace CodeDredd\\Soap;\n\nuse CodeDredd\\Soap\\Client\\Request;\nuse PHPUnit\\Framework\\Assert as PHPUnit;\n\nclass SoapTesting\n{\n    /**\n     * @var SoapFactory|null\n     */\n    protected $factory;\n\n    /**\n     * Create a new Soap Testing instance.\n     *\n     * @param  \\CodeDredd\\Soap\\SoapFactory|null  $factory\n     * @return void\n     */\n    public function __construct(SoapFactory $factory = null)\n    {\n        $this->factory = $factory;\n    }\n\n    /**\n     * Assert that a request / response pair was not recorded matching a given truth test.\n     *\n     * @param  callable  $callback\n     * @return void\n     */\n    public function assertNotSent($callback)\n    {\n        PHPUnit::assertFalse(\n            $this->factory->recorded($callback)->count() > 0,\n            'Unexpected request was recorded.'\n        );\n    }\n\n    /**\n     * Assert that no request / response pair was recorded.\n     *\n     * @return void\n     */\n    public function assertNothingSent()\n    {\n        PHPUnit::assertEmpty(\n            $this->factory->getRecorded(),\n            'Requests were recorded.'\n        );\n    }\n\n    /**\n     * Assert that every created response sequence is empty.\n     *\n     * @return void\n     */\n    public function assertSequencesAreEmpty()\n    {\n        foreach ($this->factory->getResponseSequences() as $responseSequence) {\n            PHPUnit::assertTrue(\n                $responseSequence->isEmpty(),\n                'Not all response sequences are empty.'\n            );\n        }\n    }\n\n    /**\n     * Assert that a given soap action is called with optional arguments.\n     *\n     * @param  string  $action\n     * @return void\n     */\n    public function assertActionCalled(string $action)\n    {\n        $this->assertSent(function (Request $request) use ($action) {\n            return $request->action() === $action;\n        });\n    }\n\n    /**\n     * Assert that a request / response pair was recorded matching a given truth test.\n     *\n     * @param  callable  $callback\n     * @return void\n     */\n    public function assertSent($callback)\n    {\n        PHPUnit::assertTrue(\n            $this->factory->recorded($callback)->count() > 0,\n            'An expected request was not recorded.'\n        );\n    }\n\n    /**\n     * Assert how many requests have been recorded.\n     */\n    public function assertSentCount(int $count): void\n    {\n        PHPUnit::assertCount($count, $this->factory->getRecorded());\n    }\n\n    /**\n     * Assert that the given request was sent in the given order.\n     *\n     * @param  array  $callbacks\n     * @return void\n     */\n    public function assertSentInOrder($callbacks)\n    {\n        $this->assertSentCount(count($callbacks));\n\n        foreach ($callbacks as $index => $url) {\n            $callback = is_callable($url) ? $url : function ($request) use ($url) {\n                return $request->url() == $url;\n            };\n\n            PHPUnit::assertTrue($callback(\n                $this->factory->getRecorded()[$index][0],\n                $this->factory->getRecorded()[$index][1]\n            ), 'An expected request (#'.($index + 1).') was not recorded.');\n        }\n    }\n}\n"
  },
  {
    "path": "src/Xml/XMLSerializer.php",
    "content": "<?php\n\nnamespace CodeDredd\\Soap\\Xml;\n\nuse DOMDocument;\nuse DOMNode;\nuse Illuminate\\Support\\Str;\nuse SimpleXMLElement;\n\n/**\n * Class XMLSerializer.\n */\nclass XMLSerializer\n{\n    /**\n     * Recursive function to turn a DOMDocument element to an array.\n     *\n     * @param  DOMDocument|DomNode  $node  the document (might also be a DOMElement/DOMNode?)\n     * @return array\n     */\n    public static function domNodeToArray($node)\n    {\n        $output = [];\n        switch ($node->nodeType) {\n            case XML_CDATA_SECTION_NODE:\n            case XML_TEXT_NODE:\n                $output = trim($node->textContent);\n\n                break;\n            case XML_ELEMENT_NODE:\n                for ($i = 0, $m = $node->childNodes->length; $i < $m; $i++) {\n                    $child = $node->childNodes->item($i);\n                    $v = self::domNodeToArray($child);\n                    if (isset($child->tagName)) {\n                        $t = Str::after($child->tagName, ':');\n                        if (! isset($output[$t])) {\n                            $output[$t] = [];\n                        }\n                        $output[$t][] = $v;\n                    } elseif ($v || $v === '0') {\n                        $output = is_array($v) ? json_encode($v) : $v;\n                    }\n                }\n                if ($node->attributes->length && ! is_array($output)) { // Has attributes but isn't an array\n                    $output = ['@content' => $output]; // Change output into an array.\n                }\n                if (is_array($output)) {\n                    if ($node->attributes->length) {\n                        $a = [];\n                        foreach ($node->attributes as $attrName => $attrNode) {\n                            $a[$attrName] = (string) $attrNode->value;\n                        }\n                        $output['@attributes'] = $a;\n                    }\n                    foreach ($output as $t => $v) {\n                        if (is_array($v) && count($v) == 1 && $t != '@attributes') {\n                            $output[$t] = $v[0];\n                        }\n                    }\n                }\n\n                break;\n        }\n\n        return $output;\n    }\n\n    /**\n     * Return a valid SOAP Xml.\n     *\n     * @param  array  $array\n     * @return mixed\n     */\n    public static function arrayToSoapXml(array $array)\n    {\n        $array = [\n            'SOAP-ENV:Body' => $array,\n        ];\n        $xml = new SimpleXMLElement('<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\"/>');\n        self::addArrayToXml($array, $xml);\n\n        return $xml->asXML();\n    }\n\n    public static function addArrayToXml(array $array, &$xml)\n    {\n        foreach ($array as $key => $value) {\n            if (is_array($value)) {\n                if (is_int($key)) {\n                    $key = 'node';\n                }\n                $label = $xml->addChild($key);\n                self::addArrayToXml($value, $label);\n            } else {\n                $xml->addChild($key, $value);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "tests/Fixtures/CustomSoapClient.php",
    "content": "<?php\n\nnamespace CodeDredd\\Soap\\Tests\\Fixtures;\n\nuse CodeDredd\\Soap\\SoapClient;\n\nclass CustomSoapClient extends SoapClient\n{\n    public function buildClient(string $setup = '')\n    {\n        $this->baseWsdl(__DIR__.'/Wsdl/weather.wsdl');\n        $this->withGuzzleClientOptions([\n            'handler' => $this->buildHandlerStack(),\n        ]);\n        $this->refreshEngine();\n        $this->isClientBuilded = true;\n\n        return $this;\n    }\n}\n"
  },
  {
    "path": "tests/Fixtures/Responses/SoapFault.xml",
    "content": "<?xml version='1.0' encoding='UTF-8'?>\n<soap:Envelope xmlns:soap='http://schemas.xmlsoap.org/soap/envelope'>\n    <soap:Body>\n        <soap:Fault>\n            <faultcode>soap:VersionMismatch</faultcode>\n            <faultstring xml:lang='en'>\n                Message was not SOAP 1.1 compliant\n            </faultstring>\n            <faultactor>\n                http://sample.org.ocm/jws/authnticator\n            </faultactor>\n        </soap:Fault>\n    </soap:Body>\n</soap:Envelope>\n"
  },
  {
    "path": "tests/Fixtures/Wsdl/weather.wsdl",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\nCached version of: http://wsf.cdyne.com/WeatherWS/Weather.asmx?wsdl\n-->\n<wsdl:definitions xmlns:s=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap12=\"http://schemas.xmlsoap.org/wsdl/soap12/\" xmlns:mime=\"http://schemas.xmlsoap.org/wsdl/mime/\" xmlns:tns=\"http://ws.cdyne.com/WeatherWS/\" xmlns:soap=\"http://schemas.xmlsoap.org/wsdl/soap/\" xmlns:tm=\"http://microsoft.com/wsdl/mime/textMatching/\" xmlns:http=\"http://schemas.xmlsoap.org/wsdl/http/\" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\" targetNamespace=\"http://ws.cdyne.com/WeatherWS/\" xmlns:wsdl=\"http://schemas.xmlsoap.org/wsdl/\">\n    <wsdl:types>\n        <s:schema elementFormDefault=\"qualified\" targetNamespace=\"http://ws.cdyne.com/WeatherWS/\">\n            <s:element name=\"GetWeatherInformation\">\n                <s:complexType />\n            </s:element>\n            <s:element name=\"GetWeatherInformationResponse\">\n                <s:complexType>\n                    <s:sequence>\n                        <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"GetWeatherInformationResult\" type=\"tns:ArrayOfWeatherDescription\" />\n                    </s:sequence>\n                </s:complexType>\n            </s:element>\n            <s:complexType name=\"ArrayOfWeatherDescription\">\n                <s:sequence>\n                    <s:element minOccurs=\"0\" maxOccurs=\"unbounded\" name=\"WeatherDescription\" type=\"tns:WeatherDescription\" />\n                </s:sequence>\n            </s:complexType>\n            <s:complexType name=\"WeatherDescription\">\n                <s:sequence>\n                    <s:element minOccurs=\"1\" maxOccurs=\"1\" name=\"WeatherID\" type=\"s:short\" />\n                    <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"Description\" type=\"s:string\" />\n                    <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"PictureURL\" type=\"s:string\" />\n                </s:sequence>\n            </s:complexType>\n            <s:element name=\"GetCityForecastByZIP\">\n                <s:complexType>\n                    <s:sequence>\n                        <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"ZIP\" type=\"s:string\" />\n                    </s:sequence>\n                </s:complexType>\n            </s:element>\n            <s:element name=\"GetCityForecastByZIPResponse\">\n                <s:complexType>\n                    <s:sequence>\n                        <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"GetCityForecastByZIPResult\" type=\"tns:ForecastReturn\" />\n                    </s:sequence>\n                </s:complexType>\n            </s:element>\n            <s:complexType name=\"ForecastReturn\">\n                <s:sequence>\n                    <s:element minOccurs=\"1\" maxOccurs=\"1\" name=\"Success\" type=\"s:boolean\" />\n                    <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"ResponseText\" type=\"s:string\" />\n                    <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"State\" type=\"s:string\" />\n                    <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"City\" type=\"s:string\" />\n                    <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"WeatherStationCity\" type=\"s:string\" />\n                    <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"ForecastResult\" type=\"tns:ArrayOfForecast\" />\n                </s:sequence>\n            </s:complexType>\n            <s:complexType name=\"ArrayOfForecast\">\n                <s:sequence>\n                    <s:element minOccurs=\"0\" maxOccurs=\"unbounded\" name=\"Forecast\" nillable=\"true\" type=\"tns:Forecast\" />\n                </s:sequence>\n            </s:complexType>\n            <s:complexType name=\"Forecast\">\n                <s:sequence>\n                    <s:element minOccurs=\"1\" maxOccurs=\"1\" name=\"Date\" type=\"s:dateTime\" />\n                    <s:element minOccurs=\"1\" maxOccurs=\"1\" name=\"WeatherID\" type=\"s:short\" />\n                    <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"Desciption\" type=\"s:string\" />\n                    <s:element minOccurs=\"1\" maxOccurs=\"1\" name=\"Temperatures\" type=\"tns:temp\" />\n                    <s:element minOccurs=\"1\" maxOccurs=\"1\" name=\"ProbabilityOfPrecipiation\" type=\"tns:POP\" />\n                </s:sequence>\n            </s:complexType>\n            <s:complexType name=\"temp\">\n                <s:sequence>\n                    <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"MorningLow\" type=\"s:string\" />\n                    <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"DaytimeHigh\" type=\"s:string\" />\n                </s:sequence>\n            </s:complexType>\n            <s:complexType name=\"POP\">\n                <s:sequence>\n                    <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"Nighttime\" type=\"s:string\" />\n                    <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"Daytime\" type=\"s:string\" />\n                </s:sequence>\n            </s:complexType>\n            <s:element name=\"GetCityWeatherByZIP\">\n                <s:complexType>\n                    <s:sequence>\n                        <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"ZIP\" type=\"s:string\" />\n                    </s:sequence>\n                </s:complexType>\n            </s:element>\n            <s:element name=\"GetCityWeatherByZIPResponse\">\n                <s:complexType>\n                    <s:sequence>\n                        <s:element minOccurs=\"1\" maxOccurs=\"1\" name=\"GetCityWeatherByZIPResult\" type=\"tns:WeatherReturn\" />\n                    </s:sequence>\n                </s:complexType>\n            </s:element>\n            <s:complexType name=\"WeatherReturn\">\n                <s:sequence>\n                    <s:element minOccurs=\"1\" maxOccurs=\"1\" name=\"Success\" type=\"s:boolean\" />\n                    <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"ResponseText\" type=\"s:string\" />\n                    <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"State\" type=\"s:string\" />\n                    <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"City\" type=\"s:string\" />\n                    <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"WeatherStationCity\" type=\"s:string\" />\n                    <s:element minOccurs=\"1\" maxOccurs=\"1\" name=\"WeatherID\" type=\"s:short\" />\n                    <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"Description\" type=\"s:string\" />\n                    <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"Temperature\" type=\"s:string\" />\n                    <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"RelativeHumidity\" type=\"s:string\" />\n                    <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"Wind\" type=\"s:string\" />\n                    <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"Pressure\" type=\"s:string\" />\n                    <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"Visibility\" type=\"s:string\" />\n                    <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"WindChill\" type=\"s:string\" />\n                    <s:element minOccurs=\"0\" maxOccurs=\"1\" name=\"Remarks\" type=\"s:string\" />\n                </s:sequence>\n            </s:complexType>\n            <s:element name=\"ArrayOfWeatherDescription\" nillable=\"true\" type=\"tns:ArrayOfWeatherDescription\" />\n            <s:element name=\"ForecastReturn\" nillable=\"true\" type=\"tns:ForecastReturn\" />\n            <s:element name=\"WeatherReturn\" type=\"tns:WeatherReturn\" />\n        </s:schema>\n    </wsdl:types>\n    <wsdl:message name=\"GetWeatherInformationSoapIn\">\n        <wsdl:part name=\"parameters\" element=\"tns:GetWeatherInformation\" />\n    </wsdl:message>\n    <wsdl:message name=\"GetWeatherInformationSoapOut\">\n        <wsdl:part name=\"parameters\" element=\"tns:GetWeatherInformationResponse\" />\n    </wsdl:message>\n    <wsdl:message name=\"GetCityForecastByZIPSoapIn\">\n        <wsdl:part name=\"parameters\" element=\"tns:GetCityForecastByZIP\" />\n    </wsdl:message>\n    <wsdl:message name=\"GetCityForecastByZIPSoapOut\">\n        <wsdl:part name=\"parameters\" element=\"tns:GetCityForecastByZIPResponse\" />\n    </wsdl:message>\n    <wsdl:message name=\"GetCityWeatherByZIPSoapIn\">\n        <wsdl:part name=\"parameters\" element=\"tns:GetCityWeatherByZIP\" />\n    </wsdl:message>\n    <wsdl:message name=\"GetCityWeatherByZIPSoapOut\">\n        <wsdl:part name=\"parameters\" element=\"tns:GetCityWeatherByZIPResponse\" />\n    </wsdl:message>\n    <wsdl:message name=\"GetWeatherInformationHttpGetIn\" />\n    <wsdl:message name=\"GetWeatherInformationHttpGetOut\">\n        <wsdl:part name=\"Body\" element=\"tns:ArrayOfWeatherDescription\" />\n    </wsdl:message>\n    <wsdl:message name=\"GetCityForecastByZIPHttpGetIn\">\n        <wsdl:part name=\"ZIP\" type=\"s:string\" />\n    </wsdl:message>\n    <wsdl:message name=\"GetCityForecastByZIPHttpGetOut\">\n        <wsdl:part name=\"Body\" element=\"tns:ForecastReturn\" />\n    </wsdl:message>\n    <wsdl:message name=\"GetCityWeatherByZIPHttpGetIn\">\n        <wsdl:part name=\"ZIP\" type=\"s:string\" />\n    </wsdl:message>\n    <wsdl:message name=\"GetCityWeatherByZIPHttpGetOut\">\n        <wsdl:part name=\"Body\" element=\"tns:WeatherReturn\" />\n    </wsdl:message>\n    <wsdl:message name=\"GetWeatherInformationHttpPostIn\" />\n    <wsdl:message name=\"GetWeatherInformationHttpPostOut\">\n        <wsdl:part name=\"Body\" element=\"tns:ArrayOfWeatherDescription\" />\n    </wsdl:message>\n    <wsdl:message name=\"GetCityForecastByZIPHttpPostIn\">\n        <wsdl:part name=\"ZIP\" type=\"s:string\" />\n    </wsdl:message>\n    <wsdl:message name=\"GetCityForecastByZIPHttpPostOut\">\n        <wsdl:part name=\"Body\" element=\"tns:ForecastReturn\" />\n    </wsdl:message>\n    <wsdl:message name=\"GetCityWeatherByZIPHttpPostIn\">\n        <wsdl:part name=\"ZIP\" type=\"s:string\" />\n    </wsdl:message>\n    <wsdl:message name=\"GetCityWeatherByZIPHttpPostOut\">\n        <wsdl:part name=\"Body\" element=\"tns:WeatherReturn\" />\n    </wsdl:message>\n    <wsdl:portType name=\"WeatherSoap\">\n        <wsdl:operation name=\"GetWeatherInformation\">\n            <wsdl:documentation xmlns:wsdl=\"http://schemas.xmlsoap.org/wsdl/\">Gets Information for each WeatherID</wsdl:documentation>\n            <wsdl:input message=\"tns:GetWeatherInformationSoapIn\" />\n            <wsdl:output message=\"tns:GetWeatherInformationSoapOut\" />\n        </wsdl:operation>\n        <wsdl:operation name=\"GetCityForecastByZIP\">\n            <wsdl:documentation xmlns:wsdl=\"http://schemas.xmlsoap.org/wsdl/\">Allows you to get your City Forecast Over the Next 7 Days, which is updated hourly. U.S. Only</wsdl:documentation>\n            <wsdl:input message=\"tns:GetCityForecastByZIPSoapIn\" />\n            <wsdl:output message=\"tns:GetCityForecastByZIPSoapOut\" />\n        </wsdl:operation>\n        <wsdl:operation name=\"GetCityWeatherByZIP\">\n            <wsdl:documentation xmlns:wsdl=\"http://schemas.xmlsoap.org/wsdl/\">Allows you to get your City's Weather, which is updated hourly. U.S. Only</wsdl:documentation>\n            <wsdl:input message=\"tns:GetCityWeatherByZIPSoapIn\" />\n            <wsdl:output message=\"tns:GetCityWeatherByZIPSoapOut\" />\n        </wsdl:operation>\n    </wsdl:portType>\n    <wsdl:portType name=\"WeatherHttpGet\">\n        <wsdl:operation name=\"GetWeatherInformation\">\n            <wsdl:documentation xmlns:wsdl=\"http://schemas.xmlsoap.org/wsdl/\">Gets Information for each WeatherID</wsdl:documentation>\n            <wsdl:input message=\"tns:GetWeatherInformationHttpGetIn\" />\n            <wsdl:output message=\"tns:GetWeatherInformationHttpGetOut\" />\n        </wsdl:operation>\n        <wsdl:operation name=\"GetCityForecastByZIP\">\n            <wsdl:documentation xmlns:wsdl=\"http://schemas.xmlsoap.org/wsdl/\">Allows you to get your City Forecast Over the Next 7 Days, which is updated hourly. U.S. Only</wsdl:documentation>\n            <wsdl:input message=\"tns:GetCityForecastByZIPHttpGetIn\" />\n            <wsdl:output message=\"tns:GetCityForecastByZIPHttpGetOut\" />\n        </wsdl:operation>\n        <wsdl:operation name=\"GetCityWeatherByZIP\">\n            <wsdl:documentation xmlns:wsdl=\"http://schemas.xmlsoap.org/wsdl/\">Allows you to get your City's Weather, which is updated hourly. U.S. Only</wsdl:documentation>\n            <wsdl:input message=\"tns:GetCityWeatherByZIPHttpGetIn\" />\n            <wsdl:output message=\"tns:GetCityWeatherByZIPHttpGetOut\" />\n        </wsdl:operation>\n    </wsdl:portType>\n    <wsdl:portType name=\"WeatherHttpPost\">\n        <wsdl:operation name=\"GetWeatherInformation\">\n            <wsdl:documentation xmlns:wsdl=\"http://schemas.xmlsoap.org/wsdl/\">Gets Information for each WeatherID</wsdl:documentation>\n            <wsdl:input message=\"tns:GetWeatherInformationHttpPostIn\" />\n            <wsdl:output message=\"tns:GetWeatherInformationHttpPostOut\" />\n        </wsdl:operation>\n        <wsdl:operation name=\"GetCityForecastByZIP\">\n            <wsdl:documentation xmlns:wsdl=\"http://schemas.xmlsoap.org/wsdl/\">Allows you to get your City Forecast Over the Next 7 Days, which is updated hourly. U.S. Only</wsdl:documentation>\n            <wsdl:input message=\"tns:GetCityForecastByZIPHttpPostIn\" />\n            <wsdl:output message=\"tns:GetCityForecastByZIPHttpPostOut\" />\n        </wsdl:operation>\n        <wsdl:operation name=\"GetCityWeatherByZIP\">\n            <wsdl:documentation xmlns:wsdl=\"http://schemas.xmlsoap.org/wsdl/\">Allows you to get your City's Weather, which is updated hourly. U.S. Only</wsdl:documentation>\n            <wsdl:input message=\"tns:GetCityWeatherByZIPHttpPostIn\" />\n            <wsdl:output message=\"tns:GetCityWeatherByZIPHttpPostOut\" />\n        </wsdl:operation>\n    </wsdl:portType>\n    <wsdl:binding name=\"WeatherSoap\" type=\"tns:WeatherSoap\">\n        <soap:binding transport=\"http://schemas.xmlsoap.org/soap/http\" />\n        <wsdl:operation name=\"GetWeatherInformation\">\n            <soap:operation soapAction=\"http://ws.cdyne.com/WeatherWS/GetWeatherInformation\" style=\"document\" />\n            <wsdl:input>\n                <soap:body use=\"literal\" />\n            </wsdl:input>\n            <wsdl:output>\n                <soap:body use=\"literal\" />\n            </wsdl:output>\n        </wsdl:operation>\n        <wsdl:operation name=\"GetCityForecastByZIP\">\n            <soap:operation soapAction=\"http://ws.cdyne.com/WeatherWS/GetCityForecastByZIP\" style=\"document\" />\n            <wsdl:input>\n                <soap:body use=\"literal\" />\n            </wsdl:input>\n            <wsdl:output>\n                <soap:body use=\"literal\" />\n            </wsdl:output>\n        </wsdl:operation>\n        <wsdl:operation name=\"GetCityWeatherByZIP\">\n            <soap:operation soapAction=\"http://ws.cdyne.com/WeatherWS/GetCityWeatherByZIP\" style=\"document\" />\n            <wsdl:input>\n                <soap:body use=\"literal\" />\n            </wsdl:input>\n            <wsdl:output>\n                <soap:body use=\"literal\" />\n            </wsdl:output>\n        </wsdl:operation>\n    </wsdl:binding>\n    <wsdl:binding name=\"WeatherSoap12\" type=\"tns:WeatherSoap\">\n        <soap12:binding transport=\"http://schemas.xmlsoap.org/soap/http\" />\n        <wsdl:operation name=\"GetWeatherInformation\">\n            <soap12:operation soapAction=\"http://ws.cdyne.com/WeatherWS/GetWeatherInformation\" style=\"document\" />\n            <wsdl:input>\n                <soap12:body use=\"literal\" />\n            </wsdl:input>\n            <wsdl:output>\n                <soap12:body use=\"literal\" />\n            </wsdl:output>\n        </wsdl:operation>\n        <wsdl:operation name=\"GetCityForecastByZIP\">\n            <soap12:operation soapAction=\"http://ws.cdyne.com/WeatherWS/GetCityForecastByZIP\" style=\"document\" />\n            <wsdl:input>\n                <soap12:body use=\"literal\" />\n            </wsdl:input>\n            <wsdl:output>\n                <soap12:body use=\"literal\" />\n            </wsdl:output>\n        </wsdl:operation>\n        <wsdl:operation name=\"GetCityWeatherByZIP\">\n            <soap12:operation soapAction=\"http://ws.cdyne.com/WeatherWS/GetCityWeatherByZIP\" style=\"document\" />\n            <wsdl:input>\n                <soap12:body use=\"literal\" />\n            </wsdl:input>\n            <wsdl:output>\n                <soap12:body use=\"literal\" />\n            </wsdl:output>\n        </wsdl:operation>\n    </wsdl:binding>\n    <wsdl:binding name=\"WeatherHttpGet\" type=\"tns:WeatherHttpGet\">\n        <http:binding verb=\"GET\" />\n        <wsdl:operation name=\"GetWeatherInformation\">\n            <http:operation location=\"/GetWeatherInformation\" />\n            <wsdl:input>\n                <http:urlEncoded />\n            </wsdl:input>\n            <wsdl:output>\n                <mime:mimeXml part=\"Body\" />\n            </wsdl:output>\n        </wsdl:operation>\n        <wsdl:operation name=\"GetCityForecastByZIP\">\n            <http:operation location=\"/GetCityForecastByZIP\" />\n            <wsdl:input>\n                <http:urlEncoded />\n            </wsdl:input>\n            <wsdl:output>\n                <mime:mimeXml part=\"Body\" />\n            </wsdl:output>\n        </wsdl:operation>\n        <wsdl:operation name=\"GetCityWeatherByZIP\">\n            <http:operation location=\"/GetCityWeatherByZIP\" />\n            <wsdl:input>\n                <http:urlEncoded />\n            </wsdl:input>\n            <wsdl:output>\n                <mime:mimeXml part=\"Body\" />\n            </wsdl:output>\n        </wsdl:operation>\n    </wsdl:binding>\n    <wsdl:binding name=\"WeatherHttpPost\" type=\"tns:WeatherHttpPost\">\n        <http:binding verb=\"POST\" />\n        <wsdl:operation name=\"GetWeatherInformation\">\n            <http:operation location=\"/GetWeatherInformation\" />\n            <wsdl:input>\n                <mime:content type=\"application/x-www-form-urlencoded\" />\n            </wsdl:input>\n            <wsdl:output>\n                <mime:mimeXml part=\"Body\" />\n            </wsdl:output>\n        </wsdl:operation>\n        <wsdl:operation name=\"GetCityForecastByZIP\">\n            <http:operation location=\"/GetCityForecastByZIP\" />\n            <wsdl:input>\n                <mime:content type=\"application/x-www-form-urlencoded\" />\n            </wsdl:input>\n            <wsdl:output>\n                <mime:mimeXml part=\"Body\" />\n            </wsdl:output>\n        </wsdl:operation>\n        <wsdl:operation name=\"GetCityWeatherByZIP\">\n            <http:operation location=\"/GetCityWeatherByZIP\" />\n            <wsdl:input>\n                <mime:content type=\"application/x-www-form-urlencoded\" />\n            </wsdl:input>\n            <wsdl:output>\n                <mime:mimeXml part=\"Body\" />\n            </wsdl:output>\n        </wsdl:operation>\n    </wsdl:binding>\n    <wsdl:service name=\"Weather\">\n        <wsdl:port name=\"WeatherSoap\" binding=\"tns:WeatherSoap\">\n            <soap:address location=\"http://wsf.cdyne.com/WeatherWS/Weather.asmx\" />\n        </wsdl:port>\n        <wsdl:port name=\"WeatherSoap12\" binding=\"tns:WeatherSoap12\">\n            <soap12:address location=\"http://wsf.cdyne.com/WeatherWS/Weather.asmx\" />\n        </wsdl:port>\n        <wsdl:port name=\"WeatherHttpGet\" binding=\"tns:WeatherHttpGet\">\n            <http:address location=\"http://wsf.cdyne.com/WeatherWS/Weather.asmx\" />\n        </wsdl:port>\n        <wsdl:port name=\"WeatherHttpPost\" binding=\"tns:WeatherHttpPost\">\n            <http:address location=\"http://wsf.cdyne.com/WeatherWS/Weather.asmx\" />\n        </wsdl:port>\n    </wsdl:service>\n</wsdl:definitions>\n"
  },
  {
    "path": "tests/TestCase.php",
    "content": "<?php\n\nnamespace CodeDredd\\Soap\\Tests;\n\nuse CodeDredd\\Soap\\Facades\\Soap;\nuse CodeDredd\\Soap\\SoapServiceProvider;\nuse Orchestra\\Testbench\\TestCase as OrchestraTestCase;\nuse Spatie\\LaravelRay\\RayServiceProvider;\n\nabstract class TestCase extends OrchestraTestCase\n{\n    protected $loadEnvironmentVariables = true;\n\n    /**\n     * Load package service provider.\n     *\n     * @param  \\Illuminate\\Foundation\\Application  $app\n     * @return string[]\n     */\n    protected function getPackageProviders($app)\n    {\n        return [\n            SoapServiceProvider::class,\n            RayServiceProvider::class,\n        ];\n    }\n\n    /**\n     * Load package alias.\n     *\n     * @param  \\Illuminate\\Foundation\\Application  $app\n     * @return array\n     */\n    protected function getPackageAliases($app)\n    {\n        return [\n            'Soap' => Soap::class,\n        ];\n    }\n\n    /**\n     * Define environment setup.\n     *\n     * @param  \\Illuminate\\Foundation\\Application  $app\n     * @return void\n     */\n    protected function getEnvironmentSetUp($app)\n    {\n        // Setup default wsse\n        $app['config']->set('soap.clients.laravel_soap', [\n            'base_wsdl' => __DIR__.'/Fixtures/Wsdl/weather.wsdl',\n            'with_wsse' => [\n                'user_token_name' => 'username',\n                'user_token_password' => 'password',\n            ],\n        ]);\n        $app['config']->set('soap.code.path', __DIR__.'/app');\n        $app['config']->set('soap.code.namespace', 'App\\\\Soap');\n    }\n}\n"
  },
  {
    "path": "tests/Unit/Client/ResponseTest.php",
    "content": "<?php\n\nnamespace CodeDredd\\Soap\\Tests\\Unit\\Client;\n\nuse CodeDredd\\Soap\\Client\\Response;\nuse CodeDredd\\Soap\\Tests\\TestCase;\nuse GuzzleHttp\\Psr7\\Response as Psr7Response;\n\nclass ResponseTest extends TestCase\n{\n    public function testBodyFromSoapError()\n    {\n        $xml = file_get_contents(dirname(__DIR__, 2).'/Fixtures/Responses/SoapFault.xml');\n        $soapResponse = new Response(new Psr7Response(400, [], $xml));\n        self::assertEquals('Message was not SOAP 1.1 compliant', $soapResponse->body());\n    }\n}\n"
  },
  {
    "path": "tests/Unit/Commands/MakeClientCommandTest.php",
    "content": "<?php\n\nnamespace CodeDredd\\Soap\\Tests\\Unit\\Commands;\n\nuse CodeDredd\\Soap\\Tests\\TestCase;\n\nclass MakeClientCommandTest extends TestCase\n{\n    public function testConsoleCommand()\n    {\n        $this->markTestSkipped('wsdl2Php package has been removed. Needs refactoring');\n        $this->artisan('soap:make:client --dry-run')\n            ->expectsQuestion('Please type the wsdl or the name of your client configuration if u have defined one in the config \"soap.php\"', 'laravel_soap');\n    }\n}\n"
  },
  {
    "path": "tests/Unit/Commands/MakeValidationCommandTest.php",
    "content": "<?php\n\nnamespace CodeDredd\\Soap\\Tests\\Unit\\Commands;\n\nuse CodeDredd\\Soap\\Tests\\TestCase;\n\nclass MakeValidationCommandTest extends TestCase\n{\n    public function testConsoleCommand()\n    {\n        $this->markTestSkipped('wsdl2Php package has been removed. Needs refactoring');\n        $this->artisan('soap:make:validation --dry-run')\n            ->expectsQuestion('Please type the wsdl or the name of your client configuration if u have defined one in the config \"soap.php\"', 'laravel_soap')\n            ->expectsConfirmation('Do you want to generate for every client method a validation?', 'no')\n            ->expectsQuestion('Which method do you want to generate?', 'GetWeatherInformation');\n    }\n}\n"
  },
  {
    "path": "tests/Unit/Middleware/CisDhlMiddlewareTest.php",
    "content": "<?php\n\nnamespace CodeDredd\\Soap\\Tests\\Unit\\Middleware;\n\nuse CodeDredd\\Soap\\Client\\Request;\nuse CodeDredd\\Soap\\Facades\\Soap;\nuse CodeDredd\\Soap\\Tests\\TestCase;\nuse Illuminate\\Support\\Str;\n\nclass CisDhlMiddlewareTest extends TestCase\n{\n    public function testCisDHLMiddleware()\n    {\n        Soap::fake();\n        $client = Soap::withCisDHLAuth('test', 'dhl')->baseWsdl(dirname(__DIR__, 2).'/Fixtures/Wsdl/weather.wsdl');\n        $response = $client->call('GetWeatherInformation');\n        Soap::assertSent(function (Request $request) {\n            return Str::contains($request->xmlContent(), '<cis:Authentification');\n        });\n\n        self::assertTrue($response->ok());\n    }\n}\n"
  },
  {
    "path": "tests/Unit/SoapClientTest.php",
    "content": "<?php\n\nnamespace CodeDredd\\Soap\\Tests\\Unit;\n\nuse CodeDredd\\Soap\\Client\\Events\\ConnectionFailed;\nuse CodeDredd\\Soap\\Client\\Events\\RequestSending;\nuse CodeDredd\\Soap\\Client\\Events\\ResponseReceived;\nuse CodeDredd\\Soap\\Client\\Request;\nuse CodeDredd\\Soap\\Client\\Response;\nuse CodeDredd\\Soap\\Facades\\Soap;\nuse CodeDredd\\Soap\\SoapClient;\nuse CodeDredd\\Soap\\SoapFactory;\nuse CodeDredd\\Soap\\Tests\\Fixtures\\CustomSoapClient;\nuse CodeDredd\\Soap\\Tests\\TestCase;\nuse GuzzleHttp\\RedirectMiddleware;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Support\\Str;\nuse JetBrains\\PhpStorm\\ArrayShape;\n\nclass SoapClientTest extends TestCase\n{\n    protected function setUp(): void\n    {\n        parent::setUp();\n    }\n\n    /**\n     * Test that a \"fake\" terminal returns an instance of BuilderFake.\n     *\n     * @return void\n     */\n    public function testSimpleCall()\n    {\n        Soap::fake();\n        Event::fake();\n        Soap::assertNothingSent();\n        $response = Soap::baseWsdl(dirname(__DIR__, 1).'/Fixtures/Wsdl/weather.wsdl')\n            ->call('GetWeatherInformation');\n        self::assertTrue($response->ok());\n        Soap::assertSent(function (Request $request) {\n            return $request->action() === 'GetWeatherInformation';\n        });\n        Soap::assertNotSent(function (Request $request) {\n            return $request->action() === 'GetCityWeatherByZIPSoapOut';\n        });\n        Soap::assertActionCalled('GetWeatherInformation');\n    }\n\n    public function testMagicCallByConfig()\n    {\n        Soap::fake();\n        Event::fake();\n        $response = Soap::buildClient('laravel_soap')->GetWeatherInformation();\n        self::assertTrue($response->ok());\n    }\n\n    public function testWsseWithWsaCall()\n    {\n        Soap::fake();\n        ray()->showSoapClientRequests();\n        $client = Soap::baseWsdl(dirname(__DIR__, 1).'/Fixtures/Wsdl/weather.wsdl')->withWsse([\n            'userTokenName' => 'Test',\n            'userTokenPassword' => 'passwordTest',\n            'mustUnderstand' => false,\n        ])->withWsa();\n        $response = $client->GetWeatherInformation();\n        Soap::assertSent(function (Request $request) {\n            return ! Str::contains($request->xmlContent(), 'mustUnderstand');\n        });\n        self::assertTrue($response->ok());\n    }\n\n    public function testWsseWithWsa2005Call()\n    {\n        Soap::fake();\n        ray()->showSoapClientRequests();\n        $client = Soap::baseWsdl(dirname(__DIR__, 1).'/Fixtures/Wsdl/weather.wsdl')->withWsse([\n            'userTokenName' => 'Test',\n            'userTokenPassword' => 'passwordTest',\n            'mustUnderstand' => false,\n        ])->withWsa2005();\n        $response = $client->GetWeatherInformation();\n        Soap::assertSent(function (Request $request) {\n            return ! Str::contains($request->xmlContent(), 'mustUnderstand');\n        });\n        self::assertTrue($response->ok());\n    }\n\n    public function testArrayAccessResponse()\n    {\n        Soap::fakeSequence()->push('test');\n        Event::fake();\n        $response = Soap::buildClient('laravel_soap')->GetWeatherInformation()['response'];\n        self::assertEquals('test', $response);\n    }\n\n    public function testRequestWithArguments()\n    {\n        Soap::fake();\n        Event::fake();\n\n        $arguments = [\n            'prename' => 'Corona',\n            'lastname' => 'Pandemic',\n        ];\n\n        /** @var Response $response */\n        $response = Soap::buildClient('laravel_soap')->Submit_User($arguments);\n\n        Event::assertDispatched(RequestSending::class);\n        Event::assertDispatched(ResponseReceived::class);\n        self::assertTrue($response->ok());\n        Soap::assertSent(function (Request $request) use ($arguments) {\n            return $request->arguments() === $arguments &&\n                $request->action() === 'Submit_User';\n        });\n    }\n\n    public function testSequenceFake()\n    {\n        $responseFake = ['user' => 'test'];\n        $responseFake2 = ['user' => 'test2'];\n        Event::fake();\n        Soap::fakeSequence()\n            ->push($responseFake)\n            ->whenEmpty(Soap::response($responseFake2));\n        $client = Soap::buildClient('laravel_soap');\n        $response = $client->Get_User();\n        $response2 = $client->Get_User();\n        $response3 = $client->Get_User();\n        self::assertTrue($response->ok());\n        self::assertEquals($responseFake, $response->json());\n        self::assertEquals($responseFake2, $response2->json());\n        self::assertEquals($responseFake2, $response3->json());\n\n        Soap::assertSentCount(3);\n    }\n\n    /**\n     * @dataProvider soapActionProvider\n     *\n     * @param $action\n     * @param $fake\n     * @param $exspected\n     */\n    public function testSoapFake($action, $fake, $exspected)\n    {\n        $fake = collect($fake)->map(function ($item) {\n            return Soap::response($item);\n        })->all();\n\n        Soap::fake($fake);\n        Event::fake();\n        Event::assertNotDispatched(RequestSending::class);\n        Event::assertNotDispatched(ResponseReceived::class);\n        $response = Soap::baseWsdl(dirname(__DIR__, 1).'/Fixtures/Wsdl/weather.wsdl')\n            ->call($action);\n        Event::assertDispatched(RequestSending::class);\n        Event::assertDispatched(ResponseReceived::class);\n        Event::assertNotDispatched(ConnectionFailed::class);\n        self::assertEquals($exspected, $response->json());\n    }\n\n    #[ArrayShape([\n        'without_fake_array' => 'array',\n        'with_fake_array_wrong_method' => 'array',\n        'with_fake_array' => 'array',\n        'with_fake_string' => 'array',\n    ])]\n    public static function soapActionProvider(): array\n    {\n        $fakeResponse = [\n            'GetWeatherInformation' => [\n                'Response_Data' => [\n                    'Users' => [\n                        [\n                            'name' => 'test',\n                            'field' => 'bla',\n                        ],\n                    ],\n                ],\n            ],\n            'GetCityForecastByZIP' => 'Test',\n        ];\n\n        return [\n            'without_fake_array' => ['GetCityWeatherByZIP', null, null],\n            'with_fake_array_wrong_method' => ['GetCityWeatherByZIP', $fakeResponse, null],\n            'with_fake_array' => ['GetWeatherInformation', $fakeResponse, $fakeResponse['GetWeatherInformation']],\n            'with_fake_string' => ['GetCityForecastByZIP', $fakeResponse, ['response' => 'Test']],\n        ];\n    }\n\n    public function testSoapOptions(): void\n    {\n        Soap::fake();\n        Event::fake();\n        $client = Soap::withOptions(['soap_version' => SOAP_1_2])\n            ->baseWsdl(dirname(__DIR__, 1).'/Fixtures/Wsdl/weather.wsdl');\n        $response = $client->call('GetWeatherInformation');\n        self::assertTrue($response->ok());\n        Soap::assertSent(function (Request $request) {\n            return Str::contains(\n                $request->getRequest()->getHeaderLine('Content-Type'),\n                'application/soap+xml; charset=\"utf-8\"'\n            );\n        });\n        Soap::assertActionCalled('GetWeatherInformation');\n    }\n\n    public function testRealSoapCall(): void\n    {\n        $this->markTestSkipped('Real Soap Call Testing. Comment the line out for testing');\n        ray()->showSoapClientRequests();\n        // location has to be set because the wsdl has a wrong location declaration\n        $client = Soap::baseWsdl('https://www.w3schools.com/xml/tempconvert.asmx?wsdl')\n            ->withOptions([\n                'soap_version' => SOAP_1_2,\n                'location' => 'https://www.w3schools.com/xml/tempconvert.asmx?wsdl',\n            ]);\n        $result = $client->call('FahrenheitToCelsius', [\n            'Fahrenheit' => 75,\n        ]);\n        self::assertArrayHasKey('FahrenheitToCelsiusResult', $result->json());\n\n        $result = $client->FahrenheitToCelsius([\n            'Fahrenheit' => 75,\n        ]);\n        self::assertArrayHasKey('FahrenheitToCelsiusResult', $result->json());\n    }\n\n    public function testRealSoapCallBank(): void\n    {\n        $this->markTestSkipped('Real Soap Call Testing. Comment the line out for testing');\n        ray()->showSoapClientRequests();\n        // location has to be set because the wsdl has a wrong location declaration\n        $client = Soap::baseWsdl('http://www.thomas-bayer.com/axis2/services/BLZService?wsdl')\n            ->withOptions([\n                'soap_version' => SOAP_1_2,\n                'location' => 'http://www.thomas-bayer.com/axis2/services/BLZService?wsdl',\n            ]);\n        $result = $client->call('getBank', [\n            'blz' => '74120071',\n        ]);\n        dd($result->json());\n        self::assertArrayHasKey('FahrenheitToCelsiusResult', $result->json());\n\n        $result = $client->FahrenheitToCelsius([\n            'Fahrenheit' => 75,\n        ]);\n        self::assertArrayHasKey('FahrenheitToCelsiusResult', $result->json());\n    }\n\n    /**\n     * @dataProvider soapHeaderProvider\n     *\n     * @param $header\n     * @param $exspected\n     */\n    public function testSoapWithDifferentHeaders($header, $exspected): void\n    {\n        Soap::fake();\n        Event::fake();\n        $client = Soap::withHeaders($header)->baseWsdl(dirname(__DIR__, 1).'/Fixtures/Wsdl/weather.wsdl');\n        $response = $client->call('GetWeatherInformation');\n        Soap::assertSent(function (Request $request) use ($exspected) {\n            return $request->getRequest()->getHeaderLine('test') === $exspected;\n        });\n        self::assertTrue($response->ok());\n        Soap::assertActionCalled('GetWeatherInformation');\n    }\n\n    public function testArgumentsCanBeCalledTwice(): void\n    {\n        Soap::fake();\n        Event::fake();\n        Soap::assertNothingSent();\n        $response = Soap::baseWsdl(dirname(__DIR__, 1).'/Fixtures/Wsdl/weather.wsdl')\n            ->call('GetWeatherInformation');\n        self::assertTrue($response->ok());\n        Soap::assertSent(function (Request $request) {\n            return $request->arguments() === $request->arguments();\n        });\n    }\n\n    public static function soapHeaderProvider(): array\n    {\n        $header = [\n            'test' => 'application/soap+xml; charset=\"utf-8\"',\n        ];\n\n        return [\n            'without_header' => [[], ''],\n            'with_header' => [$header, $header['test']],\n        ];\n    }\n\n    public function testSoapClientClassMayBeCustomized(): void\n    {\n        Soap::fake();\n        Event::fake();\n        $client = Soap::buildClient('laravel_soap');\n        $this->assertInstanceOf(SoapClient::class, $client);\n        SoapFactory::useClientClass(CustomSoapClient::class);\n        $client = Soap::buildClient('laravel_soap');\n        $this->assertInstanceOf(CustomSoapClient::class, $client);\n    }\n\n    public function testHandlerOptions(): void\n    {\n        Soap::fake();\n        Event::fake();\n        $client = Soap::baseWsdl(dirname(__DIR__, 1).'/Fixtures/Wsdl/weather.wsdl');\n        $response = $client->call('GetWeatherInformation');\n        self::assertTrue($response->ok());\n        self::assertEquals(true, $client->getClient()->getConfig()['verify']);\n        $client = $client->withGuzzleClientOptions([\n            'allow_redirects' => RedirectMiddleware::$defaultSettings,\n            'http_errors' => true,\n            'decode_content' => true,\n            'verify' => false,\n            'cookies' => false,\n            'idn_conversion' => false,\n        ]);\n        $response = $client->call('GetWeatherInformation');\n        self::assertTrue($response->ok());\n        self::assertEquals(false, $client->getClient()->getConfig()['verify']);\n    }\n}\n"
  },
  {
    "path": "tests/Unit/Xml/XmlSerializerTest.php",
    "content": "<?php\n\nnamespace CodeDredd\\Soap\\Tests\\Unit\\Xml;\n\nuse CodeDredd\\Soap\\Tests\\TestCase;\nuse CodeDredd\\Soap\\Xml\\XMLSerializer;\n\nclass XmlSerializerTest extends TestCase\n{\n    protected $xml = <<<'XML'\n<?xml version=\"1.0\"?>\n<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\">\n    <SOAP-ENV:Body>\n        <SOAP-ENV:prename>Code</SOAP-ENV:prename>\n        <SOAP-ENV:lastname>dredd</SOAP-ENV:lastname>\n    </SOAP-ENV:Body>\n</SOAP-ENV:Envelope>\nXML;\n\n    protected $array = [\n        'prename' => 'Code',\n        'lastname' => 'dredd',\n    ];\n\n    public function testArrayToSoapXml()\n    {\n        $soapXml = XMLSerializer::arrayToSoapXml($this->array);\n\n        self::assertXmlStringEqualsXmlString($this->xml, $soapXml);\n    }\n}\n"
  }
]