[
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*]\ncharset = utf-8\ntrim_trailing_whitespace = true\ninsert_final_newline = true\nindent_style = space\nindent_size = 4\n\n[*.yml]\nindent_style = space\nindent_size = 2\n"
  },
  {
    "path": ".gitattributes",
    "content": "/tests export-ignore\n/.editorconfig export-ignore\n/.gitattributes export-ignore\n/.gitignore export-ignore\n/.php_cs export-ignore\n/.travis.yml export-ignore\n/phpunit.xml.dist export-ignore\n/CHANGELOG.md export-ignore\n/CONTRIBUTING.md export-ignore\n/README.md export-ignore\n/.github/\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE.md",
    "content": "| Q                 | A\n| ----------------- | ---\n| Bug?              | no|yes\n| New Feature?      | no|yes\n| Framework         | Laravel|Lumen\n| Framework version | 5.x.y\n| Package version   | 1.x.y\n| PHP version       | 5.x.y|7.x.y\n\n#### Actual Behaviour\n\nDescribe the behaviour you're experiencing. Do not just copy and paste a random error message and expect help.\n\n\n#### Expected Behaviour\n\nDescribe the behaviour you're expecting.\n\n\n#### Steps to Reproduce\n\nList all the steps needed to reproduce the issue you're having. Make sure to include code (affected models, configurations),\nany screenshots and/or other resources that may help us understand what's going on.\n\n\n#### Possible Solutions\n\nIf you have any ideas on how to solve the issue, add them here, otherwise you can omit this part.\n"
  },
  {
    "path": ".gitignore",
    "content": ".php_cs.cache\n.idea\ncomposer.lock\nphpunit.xml\nstorage\nvendor\n.php_cs\n"
  },
  {
    "path": ".styleci.yml",
    "content": "preset: laravel\n\ndisabled:\n  - alpha_ordered_imports\n\nenabled:\n  - phpdoc_order\n  - phpdoc_separation\n  - unalign_double_arrow\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: php\n\nsudo: false\ndist: trusty\n\nenv:\n  global:\n    - setup=basic\n    - xdebug=true\n\ncache:\n  directories:\n    - $HOME/.composer/cache\n\nmatrix:\n  include:\n    - php: 7.2\n      env: xdebug=false\n    - php: 7.3\n      env: xdebug=false\n    - php: 7.4\n      env: xdebug=false\n\nbefore_install:\n  - if [[ $xdebug = 'true' ]] ; then phpenv config-rm xdebug.ini; fi\n\ninstall:\n  - if [[ $setup = 'basic' ]]; then travis_retry composer install --prefer-dist --no-interaction --no-suggest; fi\n  - if [[ $setup = 'stable' ]]; then travis_retry composer update --prefer-dist --no-interaction --no-suggest --prefer-stable; fi\n  - if [[ $setup = 'lowest' ]]; then travis_retry composer update --prefer-dist --no-interaction --no-suggest --prefer-stable --prefer-lowest; fi\n\nscript:\n  - vendor/bin/phpunit\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# CONTRIBUTING\n\nContributions are welcome, and are accepted via pull requests. Please review these guidelines before submitting any pull requests.\n\n## Guidelines\n\n* Please follow the [PSR-2 Coding Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md).\n* Ensure that the current tests pass, and if you've added something new, add the tests where relevant.\n* Remember that we follow [SemVer](http://semver.org). If you are changing the behaviour, or the public api, you may need to update the docs.\n* Send a coherent commit history, making sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please [squash](http://git-scm.com/book/en/Git-Tools-Rewriting-History) them before submitting.\n* You may also need to [rebase](http://git-scm.com/book/en/Git-Branching-Rebasing) to avoid merge conflicts.\n\n## Running Tests\n\nYou will need an install of [Composer](https://getcomposer.org) before continuing.\n\nFirst, install the dependencies:\n\n```bash\n$ composer install\n```\n\nThen run phpunit:\n\n```bash\n$ vendor/bin/phpunit\n```\n\nIf the test suite passes on your local machine you should be good to go.\n\nWhen you make a pull request, the tests will automatically be run again by [Travis CI](https://travis-ci.org/) on multiple php versions and hhvm.\n"
  },
  {
    "path": "LICENSE",
    "content": "Copyright (c) 2014-2015, Jason Lewis\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice, this\n  list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright notice,\n  this list of conditions and the following disclaimer in the documentation\n  and/or other materials provided with the distribution.\n\n* Neither the name of Dingo API nor the names of its\n  contributors may be used to endorse or promote products derived from\n  this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\nOR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "composer.json",
    "content": "{\n    \"name\": \"dingo/api\",\n    \"description\": \"A RESTful API package for the Laravel and Lumen frameworks.\",\n    \"keywords\": [\n        \"api\",\n        \"dingo\",\n        \"laravel\",\n        \"restful\"\n    ],\n    \"license\": \"BSD-3-Clause\",\n    \"authors\": [{\n        \"name\": \"Jason Lewis\",\n        \"email\": \"jason.lewis1991@gmail.com\"\n    }],\n    \"require\": {\n        \"php\": \"^7.2.5|^8.0\",\n        \"dingo/blueprint\": \"^0.4\",\n        \"illuminate/routing\": \"^7.0|^8.0\",\n        \"illuminate/support\": \"^7.0|^8.0\",\n        \"league/fractal\": \"^0.19\"\n    },\n    \"require-dev\": {\n        \"friendsofphp/php-cs-fixer\": \"~2\",\n        \"illuminate/auth\": \"^7.0|^8.0\",\n        \"illuminate/cache\": \"^7.0|^8.0\",\n        \"illuminate/console\": \"^7.0|^8.0\",\n        \"illuminate/database\": \"^7.0|^8.0\",\n        \"illuminate/events\": \"^7.0|^8.0\",\n        \"illuminate/filesystem\": \"^7.0|^8.0\",\n        \"illuminate/log\": \"^7.0|^8.0\",\n        \"illuminate/pagination\": \"^7.0|^8.0\",\n        \"laravel/lumen-framework\": \"^7.0|^8.0\",\n        \"mockery/mockery\": \"~1.0\",\n        \"phpunit/phpunit\": \"^8.5|^9.0\",\n        \"squizlabs/php_codesniffer\": \"~2.0\",\n        \"tymon/jwt-auth\": \"1.0.*\"\n    },\n    \"suggest\": {\n        \"tymon/jwt-auth\": \"Protect your API with JSON Web Tokens.\"\n    },\n    \"abandoned\": \"api-ecosystem-for-laravel/dingo-api\",\n    \"autoload\": {\n        \"psr-4\": {\n            \"Dingo\\\\Api\\\\\": \"src/\"\n        },\n        \"files\": [\n            \"src/helpers.php\"\n        ]\n    },\n    \"autoload-dev\": {\n        \"psr-4\": {\n            \"Dingo\\\\Api\\\\Tests\\\\\": \"tests/\"\n        }\n    },\n    \"extra\": {\n        \"branch-alias\": {\n            \"dev-master\": \"2.0-dev\"\n        },\n        \"laravel\": {\n            \"providers\": [\n                \"Dingo\\\\Api\\\\Provider\\\\LaravelServiceProvider\"\n            ],\n            \"aliases\": {\n                \"API\": \"Dingo\\\\Api\\\\Facade\\\\API\"\n            }\n        }\n    },\n    \"config\": {\n        \"sort-packages\": true\n    },\n    \"minimum-stability\": \"dev\",\n    \"prefer-stable\": true\n}\n"
  },
  {
    "path": "config/api.php",
    "content": "<?php\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | Standards Tree\n    |--------------------------------------------------------------------------\n    |\n    | Versioning an API with Dingo revolves around content negotiation and\n    | custom MIME types. A custom type will belong to one of three\n    | standards trees, the Vendor tree (vnd), the Personal tree\n    | (prs), and the Unregistered tree (x).\n    |\n    | By default the Unregistered tree (x) is used, however, should you wish\n    | to you can register your type with the IANA. For more details:\n    | https://tools.ietf.org/html/rfc6838\n    |\n    */\n\n    'standardsTree' => env('API_STANDARDS_TREE', 'x'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | API Subtype\n    |--------------------------------------------------------------------------\n    |\n    | Your subtype will follow the standards tree you use when used in the\n    | \"Accept\" header to negotiate the content type and version.\n    |\n    | For example: Accept: application/x.SUBTYPE.v1+json\n    |\n    */\n\n    'subtype' => env('API_SUBTYPE', ''),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Default API Version\n    |--------------------------------------------------------------------------\n    |\n    | This is the default version when strict mode is disabled and your API\n    | is accessed via a web browser. It's also used as the default version\n    | when generating your APIs documentation.\n    |\n    */\n\n    'version' => env('API_VERSION', 'v1'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Default API Prefix\n    |--------------------------------------------------------------------------\n    |\n    | A default prefix to use for your API routes so you don't have to\n    | specify it for each group.\n    |\n    */\n\n    'prefix' => env('API_PREFIX', null),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Default API Domain\n    |--------------------------------------------------------------------------\n    |\n    | A default domain to use for your API routes so you don't have to\n    | specify it for each group.\n    |\n    */\n\n    'domain' => env('API_DOMAIN', null),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Name\n    |--------------------------------------------------------------------------\n    |\n    | When documenting your API using the API Blueprint syntax you can\n    | configure a default name to avoid having to manually specify\n    | one when using the command.\n    |\n    */\n\n    'name' => env('API_NAME', null),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Conditional Requests\n    |--------------------------------------------------------------------------\n    |\n    | Globally enable conditional requests so that an ETag header is added to\n    | any successful response. Subsequent requests will perform a check and\n    | will return a 304 Not Modified. This can also be enabled or disabled\n    | on certain groups or routes.\n    |\n    */\n\n    'conditionalRequest' => env('API_CONDITIONAL_REQUEST', true),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Strict Mode\n    |--------------------------------------------------------------------------\n    |\n    | Enabling strict mode will require clients to send a valid Accept header\n    | with every request. This also voids the default API version, meaning\n    | your API will not be browsable via a web browser.\n    |\n    */\n\n    'strict' => env('API_STRICT', false),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Debug Mode\n    |--------------------------------------------------------------------------\n    |\n    | Enabling debug mode will result in error responses caused by thrown\n    | exceptions to have a \"debug\" key that will be populated with\n    | more detailed information on the exception.\n    |\n    */\n\n    'debug' => env('API_DEBUG', false),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Generic Error Format\n    |--------------------------------------------------------------------------\n    |\n    | When some HTTP exceptions are not caught and dealt with the API will\n    | generate a generic error response in the format provided. Any\n    | keys that aren't replaced with corresponding values will be\n    | removed from the final response.\n    |\n    */\n\n    'errorFormat' => [\n        'message' => ':message',\n        'errors' => ':errors',\n        'code' => ':code',\n        'status_code' => ':status_code',\n        'debug' => ':debug',\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | API Middleware\n    |--------------------------------------------------------------------------\n    |\n    | Middleware that will be applied globally to all API requests.\n    |\n    */\n\n    'middleware' => [\n\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Authentication Providers\n    |--------------------------------------------------------------------------\n    |\n    | The authentication providers that should be used when attempting to\n    | authenticate an incoming API request.\n    |\n    */\n\n    'auth' => [\n\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Throttling / Rate Limiting\n    |--------------------------------------------------------------------------\n    |\n    | Consumers of your API can be limited to the amount of requests they can\n    | make. You can create your own throttles or simply change the default\n    | throttles.\n    |\n    */\n\n    'throttling' => [\n\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Response Transformer\n    |--------------------------------------------------------------------------\n    |\n    | Responses can be transformed so that they are easier to format. By\n    | default a Fractal transformer will be used to transform any\n    | responses prior to formatting. You can easily replace\n    | this with your own transformer.\n    |\n    */\n\n    'transformer' => env('API_TRANSFORMER', Dingo\\Api\\Transformer\\Adapter\\Fractal::class),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Response Formats\n    |--------------------------------------------------------------------------\n    |\n    | Responses can be returned in multiple formats by registering different\n    | response formatters. You can also customize an existing response\n    | formatter with a number of options to configure its output.\n    |\n    */\n\n    'defaultFormat' => env('API_DEFAULT_FORMAT', 'json'),\n\n    'formats' => [\n\n        'json' => Dingo\\Api\\Http\\Response\\Format\\Json::class,\n\n    ],\n\n    'formatsOptions' => [\n\n        'json' => [\n            'pretty_print' => env('API_JSON_FORMAT_PRETTY_PRINT_ENABLED', false),\n            'indent_style' => env('API_JSON_FORMAT_INDENT_STYLE', 'space'),\n            'indent_size' => env('API_JSON_FORMAT_INDENT_SIZE', 2),\n        ],\n\n    ],\n\n];\n"
  },
  {
    "path": "phpunit.xml.dist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<phpunit backupGlobals=\"false\"\n         backupStaticAttributes=\"false\"\n         beStrictAboutTestsThatDoNotTestAnything=\"true\"\n         beStrictAboutOutputDuringTests=\"true\"\n         bootstrap=\"vendor/autoload.php\"\n         colors=\"true\"\n         convertErrorsToExceptions=\"true\"\n         convertNoticesToExceptions=\"true\"\n         convertWarningsToExceptions=\"true\"\n         failOnRisky=\"true\"\n         failOnWarning=\"true\"\n         processIsolation=\"false\"\n         stopOnError=\"false\"\n         stopOnFailure=\"false\"\n         verbose=\"true\"\n    >\n    <testsuites>\n        <testsuite name=\"API Test Suite\">\n            <directory suffix=\"Test.php\">./tests</directory>\n            <exclude>./tests/Routing/Adapter/LumenTest.php</exclude>\n        </testsuite>\n    </testsuites>\n    <filter>\n        <whitelist processUncoveredFilesFromWhitelist=\"true\">\n            <directory suffix=\".php\">./src</directory>\n        </whitelist>\n    </filter>\n</phpunit>\n"
  },
  {
    "path": "readme.md",
    "content": "# Move repositories notice\nUnfortunately this package cannot be maintained at this location anymore due to broken CI integrations, and travis-ci likely can't be used much longer either due to their change to paid plans. This project is still being actively maintained, we ask you to please switch to the following repository: https://github.com/api-ecosystem-for-laravel/dingo-api\n\n---\n\n![](https://cloud.githubusercontent.com/assets/829059/9216039/82be51cc-40f6-11e5-88f5-f0cbd07bcc39.png)\n\nThe Dingo API package is meant to provide you, the developer, with a set of tools to help you easily and quickly build your own API. While the goal of this package is to remain as flexible as possible it still won't cover all situations and solve all problems.\n\n[![Build Status](https://img.shields.io/travis/dingo/api/master.svg?style=flat-square)](https://travis-ci.org/dingo/api)\n[![License](https://img.shields.io/packagist/l/dingo/api.svg?style=flat-square)](LICENSE)\n[![Development Version](https://img.shields.io/packagist/vpre/dingo/api.svg?style=flat-square)](https://packagist.org/packages/dingo/api)\n[![Monthly Installs](https://img.shields.io/packagist/dm/dingo/api.svg?style=flat-square)](https://packagist.org/packages/dingo/api)\n[![StyleCI](https://styleci.io/repos/18673522/shield)](https://styleci.io/repos/18673522)\n\n## Features\n\nThis package provides tools for the following, and more:\n\n- Content Negotiation\n- Multiple Authentication Adapters\n- API Versioning\n- Rate Limiting\n- Response Transformers and Formatters\n- Error and Exception Handling\n- Internal Requests\n- API Blueprint Documentation\n\n## Documentation\n\nPlease refer to our extensive [Wiki documentation](https://github.com/dingo/api/wiki) for more information.\n\n## API Boilerplate\n\nIf you are looking to start a new project from scratch, consider using the [Laravel API Boilerplate](https://github.com/specialtactics/laravel-api-boilerplate), which builds on top of the dingo-api package, and adds a lot of great features.\n\n## Support\n\nFor answers you may not find in the Wiki, avoid posting issues. Feel free to ask for support on the dedicated [Slack](https://larachat.slack.com/messages/api/) room. Make sure to mention **specialtactics** so he is notified.\n\n## License\n\nThis package is licensed under the [BSD 3-Clause license](http://opensource.org/licenses/BSD-3-Clause).\n"
  },
  {
    "path": "src/Auth/Auth.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Auth;\n\nuse Exception;\nuse Dingo\\Api\\Routing\\Router;\nuse Illuminate\\Container\\Container;\nuse Symfony\\Component\\HttpKernel\\Exception\\BadRequestHttpException;\nuse Symfony\\Component\\HttpKernel\\Exception\\UnauthorizedHttpException;\n\nclass Auth\n{\n    /**\n     * Router instance.\n     *\n     * @var \\Dingo\\Api\\Routing\\Router\n     */\n    protected $router;\n\n    /**\n     * Illuminate container instance.\n     *\n     * @var \\Illuminate\\Container\\Container\n     */\n    protected $container;\n\n    /**\n     * Array of available authentication providers.\n     *\n     * @var array\n     */\n    protected $providers;\n\n    /**\n     * The provider used for authentication.\n     *\n     * @var \\Dingo\\Api\\Contract\\Auth\\Provider\n     */\n    protected $providerUsed;\n\n    /**\n     * Authenticated user instance.\n     *\n     * @var \\Illuminate\\Auth\\GenericUser|\\Illuminate\\Database\\Eloquent\\Model\n     */\n    protected $user;\n\n    /**\n     * Create a new auth instance.\n     *\n     * @param \\Dingo\\Api\\Routing\\Router       $router\n     * @param \\Illuminate\\Container\\Container $container\n     * @param array                           $providers\n     *\n     * @return void\n     */\n    public function __construct(Router $router, Container $container, array $providers)\n    {\n        $this->router = $router;\n        $this->container = $container;\n        $this->providers = $providers;\n    }\n\n    /**\n     * Authenticate the current request.\n     *\n     * @param array $providers\n     *\n     * @throws \\Symfony\\Component\\HttpKernel\\Exception\\UnauthorizedHttpException\n     *\n     * @return mixed\n     */\n    public function authenticate(array $providers = [])\n    {\n        $exceptionStack = [];\n\n        // Spin through each of the registered authentication providers and attempt to\n        // authenticate through one of them. This allows a developer to implement\n        // and allow a number of different authentication mechanisms.\n        foreach ($this->filterProviders($providers) as $provider) {\n            try {\n                $user = $provider->authenticate($this->router->getCurrentRequest(), $this->router->getCurrentRoute());\n\n                $this->providerUsed = $provider;\n\n                return $this->user = $user;\n            } catch (UnauthorizedHttpException $exception) {\n                $exceptionStack[] = $exception;\n            } catch (BadRequestHttpException $exception) {\n                // We won't add this exception to the stack as it's thrown when the provider\n                // is unable to authenticate due to the correct authorization header not\n                // being set. We will throw an exception for this below.\n            }\n        }\n\n        $this->throwUnauthorizedException($exceptionStack);\n    }\n\n    /**\n     * Throw the first exception from the exception stack.\n     *\n     * @param array $exceptionStack\n     *\n     * @throws \\Symfony\\Component\\HttpKernel\\Exception\\UnauthorizedHttpException\n     *\n     * @return void\n     */\n    protected function throwUnauthorizedException(array $exceptionStack)\n    {\n        $exception = array_shift($exceptionStack);\n\n        if ($exception === null) {\n            $exception = new UnauthorizedHttpException('dingo', 'Failed to authenticate because of bad credentials or an invalid authorization header.');\n        }\n\n        throw $exception;\n    }\n\n    /**\n     * Filter the requested providers from the available providers.\n     *\n     * @param array $providers\n     *\n     * @return array\n     */\n    protected function filterProviders(array $providers)\n    {\n        if (empty($providers)) {\n            return $this->providers;\n        }\n\n        return array_intersect_key($this->providers, array_flip($providers));\n    }\n\n    /**\n     * Get the authenticated user.\n     *\n     * @param bool $authenticate\n     *\n     * @return \\Illuminate\\Auth\\GenericUser|\\Illuminate\\Database\\Eloquent\\Model|null\n     */\n    public function getUser($authenticate = true)\n    {\n        if ($this->user) {\n            return $this->user;\n        } elseif (! $authenticate) {\n            return;\n        }\n\n        try {\n            return $this->user = $this->authenticate();\n        } catch (Exception $exception) {\n            return;\n        }\n    }\n\n    /**\n     * Alias for getUser.\n     *\n     * @param bool $authenticate\n     *\n     * @return \\Illuminate\\Auth\\GenericUser|\\Illuminate\\Database\\Eloquent\\Model\n     */\n    public function user($authenticate = true)\n    {\n        return $this->getUser($authenticate);\n    }\n\n    /**\n     * Set the authenticated user.\n     *\n     * @param \\Illuminate\\Auth\\GenericUser|\\Illuminate\\Database\\Eloquent\\Model $user\n     *\n     * @return \\Dingo\\Api\\Auth\\Auth\n     */\n    public function setUser($user)\n    {\n        $this->user = $user;\n\n        return $this;\n    }\n\n    /**\n     * Check if a user has authenticated with the API.\n     *\n     * @param bool $authenticate\n     *\n     * @return bool\n     */\n    public function check($authenticate = false)\n    {\n        return ! is_null($this->user($authenticate));\n    }\n\n    /**\n     * Get the provider used for authentication.\n     *\n     * @return \\Dingo\\Api\\Contract\\Auth\\Provider\n     */\n    public function getProviderUsed()\n    {\n        return $this->providerUsed;\n    }\n\n    /**\n     * Extend the authentication layer with a custom provider.\n     *\n     * @param string          $key\n     * @param object|callable $provider\n     *\n     * @return void\n     */\n    public function extend($key, $provider)\n    {\n        if (is_callable($provider)) {\n            $provider = call_user_func($provider, $this->container);\n        }\n\n        $this->providers[$key] = $provider;\n    }\n}\n"
  },
  {
    "path": "src/Auth/Provider/Authorization.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Auth\\Provider;\n\nuse Illuminate\\Support\\Str;\nuse Illuminate\\Http\\Request;\nuse Symfony\\Component\\HttpKernel\\Exception\\BadRequestHttpException;\n\nabstract class Authorization implements \\Dingo\\Api\\Contract\\Auth\\Provider\n{\n    /**\n     * Array of provider specific options.\n     *\n     * @var array\n     */\n    protected $options = [];\n\n    /**\n     * Validate the requests authorization header for the provider.\n     *\n     * @param \\Illuminate\\Http\\Request $request\n     *\n     * @throws \\Symfony\\Component\\HttpKernel\\Exception\\BadRequestHttpException\n     *\n     * @return bool\n     */\n    public function validateAuthorizationHeader(Request $request)\n    {\n        if (Str::startsWith(strtolower($request->headers->get('authorization')), $this->getAuthorizationMethod())) {\n            return true;\n        }\n\n        throw new BadRequestHttpException;\n    }\n\n    /**\n     * Get the providers authorization method.\n     *\n     * @return string\n     */\n    abstract public function getAuthorizationMethod();\n}\n"
  },
  {
    "path": "src/Auth/Provider/Basic.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Auth\\Provider;\n\nuse Dingo\\Api\\Routing\\Route;\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Auth\\AuthManager;\nuse Symfony\\Component\\HttpKernel\\Exception\\UnauthorizedHttpException;\n\nclass Basic extends Authorization\n{\n    /**\n     * Illuminate authentication manager.\n     *\n     * @var \\Illuminate\\Auth\\AuthManager\n     */\n    protected $auth;\n\n    /**\n     * Basic auth identifier.\n     *\n     * @var string\n     */\n    protected $identifier;\n\n    /**\n     * Create a new basic provider instance.\n     *\n     * @param \\Illuminate\\Auth\\AuthManager $auth\n     * @param string                       $identifier\n     *\n     * @return void\n     */\n    public function __construct(AuthManager $auth, $identifier = 'email')\n    {\n        $this->auth = $auth;\n        $this->identifier = $identifier;\n    }\n\n    /**\n     * Authenticate request with Basic.\n     *\n     * @param \\Illuminate\\Http\\Request $request\n     * @param \\Dingo\\Api\\Routing\\Route $route\n     *\n     * @return mixed\n     */\n    public function authenticate(Request $request, Route $route)\n    {\n        $this->validateAuthorizationHeader($request);\n\n        if (($response = $this->auth->onceBasic($this->identifier)) && $response->getStatusCode() === 401) {\n            throw new UnauthorizedHttpException('Basic', 'Invalid authentication credentials.');\n        }\n\n        return $this->auth->user();\n    }\n\n    /**\n     * Get the providers authorization method.\n     *\n     * @return string\n     */\n    public function getAuthorizationMethod()\n    {\n        return 'basic';\n    }\n}\n"
  },
  {
    "path": "src/Auth/Provider/JWT.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Auth\\Provider;\n\nuse Exception;\nuse Tymon\\JWTAuth\\JWTAuth;\nuse Dingo\\Api\\Routing\\Route;\nuse Illuminate\\Http\\Request;\nuse Tymon\\JWTAuth\\Exceptions\\JWTException;\nuse Symfony\\Component\\HttpKernel\\Exception\\UnauthorizedHttpException;\n\nclass JWT extends Authorization\n{\n    /**\n     * The JWTAuth instance.\n     *\n     * @var \\Tymon\\JWTAuth\\JWTAuth\n     */\n    protected $auth;\n\n    /**\n     * Create a new JWT provider instance.\n     *\n     * @param \\Tymon\\JWTAuth\\JWTAuth $auth\n     *\n     * @return void\n     */\n    public function __construct(JWTAuth $auth)\n    {\n        $this->auth = $auth;\n    }\n\n    /**\n     * Authenticate request with a JWT.\n     *\n     * @param \\Illuminate\\Http\\Request $request\n     * @param \\Dingo\\Api\\Routing\\Route $route\n     *\n     * @return mixed\n     */\n    public function authenticate(Request $request, Route $route)\n    {\n        $token = $this->getToken($request);\n\n        try {\n            if (! $user = $this->auth->setToken($token)->authenticate()) {\n                throw new UnauthorizedHttpException('JWTAuth', 'Unable to authenticate with invalid token.');\n            }\n        } catch (JWTException $exception) {\n            throw new UnauthorizedHttpException('JWTAuth', $exception->getMessage(), $exception);\n        }\n\n        return $user;\n    }\n\n    /**\n     * Get the JWT from the request.\n     *\n     * @param \\Illuminate\\Http\\Request $request\n     *\n     * @throws \\Exception\n     *\n     * @return string\n     */\n    protected function getToken(Request $request)\n    {\n        try {\n            $this->validateAuthorizationHeader($request);\n\n            $token = $this->parseAuthorizationHeader($request);\n        } catch (Exception $exception) {\n            if (! $token = $request->query('token', false)) {\n                throw $exception;\n            }\n        }\n\n        return $token;\n    }\n\n    /**\n     * Parse JWT from the authorization header.\n     *\n     * @param \\Illuminate\\Http\\Request $request\n     *\n     * @return string\n     */\n    protected function parseAuthorizationHeader(Request $request)\n    {\n        return trim(str_ireplace($this->getAuthorizationMethod(), '', $request->header('authorization')));\n    }\n\n    /**\n     * Get the providers authorization method.\n     *\n     * @return string\n     */\n    public function getAuthorizationMethod()\n    {\n        return 'bearer';\n    }\n}\n"
  },
  {
    "path": "src/Console/Command/Cache.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Console\\Command;\n\nuse Dingo\\Api\\Routing\\Router;\nuse Illuminate\\Console\\Command;\nuse Illuminate\\Filesystem\\Filesystem;\nuse Dingo\\Api\\Contract\\Routing\\Adapter;\nuse Illuminate\\Contracts\\Console\\Kernel;\n\nclass Cache extends Command\n{\n    /**\n     * The name and signature of the console command.\n     *\n     * @var string\n     */\n    public $signature = 'api:cache';\n\n    /**\n     * The console command description.\n     *\n     * @var string\n     */\n    public $description = 'Create a route cache file for faster route registration';\n\n    /**\n     * Filesystem instance.\n     *\n     * @var \\Illuminate\\Filesystem\\Filesystem\n     */\n    protected $files;\n\n    /**\n     * Router instance.\n     *\n     * @var \\Dingo\\Api\\Routing\\Router\n     */\n    private $router;\n\n    /**\n     * Adapter instance.\n     *\n     * @var \\Dingo\\Api\\Contract\\Routing\\Adapter\n     */\n    private $adapter;\n\n    /**\n     * Create a new cache command instance.\n     *\n     * @param \\Illuminate\\Filesystem\\Filesystem   $files\n     * @param \\Dingo\\Api\\Routing\\Router           $router\n     * @param \\Dingo\\Api\\Contract\\Routing\\Adapter $adapter\n     *\n     * @return void\n     */\n    public function __construct(Filesystem $files, Router $router, Adapter $adapter)\n    {\n        $this->files = $files;\n        $this->router = $router;\n        $this->adapter = $adapter;\n\n        parent::__construct();\n    }\n\n    /**\n     * Execute the console command.\n     *\n     * @return mixed\n     */\n    public function handle()\n    {\n        $this->callSilent('route:clear');\n\n        $app = $this->getFreshApplication();\n\n        $this->call('route:cache');\n\n        $routes = $app['api.router']->getAdapterRoutes();\n\n        foreach ($routes as $collection) {\n            foreach ($collection as $route) {\n                $app['api.router.adapter']->prepareRouteForSerialization($route);\n            }\n        }\n\n        $stub = \"app('api.router')->setAdapterRoutes(unserialize(base64_decode('{{routes}}')));\";\n        $path = $this->laravel->getCachedRoutesPath();\n\n        if (! $this->files->exists($path)) {\n            $stub = \"<?php\\n\\n$stub\";\n        }\n\n        $this->files->append(\n            $path,\n            str_replace('{{routes}}', base64_encode(serialize($routes)), $stub)\n        );\n    }\n\n    /**\n     * Get a fresh application instance.\n     *\n     * @return \\Illuminate\\Contracts\\Container\\Container\n     */\n    protected function getFreshApplication()\n    {\n        if (method_exists($this->laravel, 'bootstrapPath')) {\n            $app = require $this->laravel->bootstrapPath().'/app.php';\n        } else {\n            $app = require $this->laravel->basePath().'/bootstrap/app.php';\n        }\n\n        $app->make(Kernel::class)->bootstrap();\n\n        return $app;\n    }\n}\n"
  },
  {
    "path": "src/Console/Command/Docs.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Console\\Command;\n\nuse ReflectionClass;\nuse Dingo\\Blueprint\\Writer;\nuse Illuminate\\Support\\Arr;\nuse Illuminate\\Support\\Str;\nuse Dingo\\Api\\Routing\\Router;\nuse Dingo\\Blueprint\\Blueprint;\nuse Illuminate\\Console\\Command;\nuse Illuminate\\Support\\Collection;\n\nclass Docs extends Command\n{\n    /**\n     * Router instance.\n     *\n     * @var \\Dingo\\Api\\Routing\\Router\n     */\n    protected $router;\n\n    /**\n     * The blueprint instance.\n     *\n     * @var \\Dingo\\Blueprint\\Blueprint\n     */\n    protected $blueprint;\n\n    /**\n     * Blueprint instance.\n     *\n     * @var \\Dingo\\Blueprint\\Blueprint\n     */\n    protected $docs;\n\n    /**\n     * Writer instance.\n     *\n     * @var \\Dingo\\Blueprint\\Writer\n     */\n    protected $writer;\n\n    /**\n     * Default documentation name.\n     *\n     * @var string\n     */\n    protected $name;\n\n    /**\n     * Default documentation version.\n     *\n     * @var string\n     */\n    protected $version;\n\n    /**\n     * The name and signature of the console command.\n     *\n     * @var string\n     */\n    protected $signature = 'api:docs {--name= : Name of the generated documentation}\n                                     {--use-version= : Version of the documentation to be generated}\n                                     {--output-file= : Output the generated documentation to a file}\n                                     {--include-path= : Path where included documentation files are located}\n                                     {--use-controller= : Specify a controller where to generate documentation for}';\n\n    /**\n     * The console command description.\n     *\n     * @var string\n     */\n    protected $description = 'Generate API documentation from annotated controllers';\n\n    /**\n     * Create a new docs command instance.\n     *\n     * @param \\Dingo\\Api\\Routing\\Router  $router\n     * @param \\Dingo\\Blueprint\\Blueprint $blueprint\n     * @param \\Dingo\\Blueprint\\Writer    $writer\n     * @param string                     $name\n     * @param string                     $version\n     *\n     * @return void\n     */\n    public function __construct(Router $router, Blueprint $blueprint, Writer $writer, $name, $version)\n    {\n        parent::__construct();\n\n        $this->router = $router;\n        $this->blueprint = $blueprint;\n        $this->writer = $writer;\n        $this->name = $name;\n        $this->version = $version;\n    }\n\n    /**\n     * Execute the console command.\n     *\n     * @return mixed\n     */\n    public function handle()\n    {\n        $contents = $this->blueprint->generate($this->getControllers(), $this->getDocName(), $this->getVersion(), $this->getIncludePath());\n\n        if ($file = $this->option('output-file')) {\n            $this->writer->write($contents, $file);\n\n            return $this->info('Documentation was generated successfully.');\n        }\n\n        return $this->line($contents);\n    }\n\n    /**\n     * Get the documentation name.\n     *\n     * @return string\n     */\n    protected function getDocName()\n    {\n        $name = $this->option('name') ?: $this->name;\n\n        if (! $name) {\n            $this->comment('A name for the documentation was not supplied. Use the --name option or set a default in the configuration.');\n\n            exit;\n        }\n\n        return $name;\n    }\n\n    /**\n     * Get the include path for documentation files.\n     *\n     * @return string\n     */\n    protected function getIncludePath()\n    {\n        return base_path($this->option('include-path'));\n    }\n\n    /**\n     * Get the documentation version.\n     *\n     * @return string\n     */\n    protected function getVersion()\n    {\n        $version = $this->option('use-version') ?: $this->version;\n\n        if (! $version) {\n            $this->comment('A version for the documentation was not supplied. Use the --use-version option or set a default in the configuration.');\n\n            exit;\n        }\n\n        return $version;\n    }\n\n    /**\n     * Get all the controller instances.\n     *\n     * @return array\n     */\n    protected function getControllers()\n    {\n        $controllers = new Collection;\n\n        if ($controller = $this->option('use-controller')) {\n            $this->addControllerIfNotExists($controllers, app($controller));\n\n            return $controllers;\n        }\n\n        foreach ($this->router->getRoutes() as $collections) {\n            foreach ($collections as $route) {\n                if ($controller = $route->getControllerInstance()) {\n                    $this->addControllerIfNotExists($controllers, $controller);\n                }\n            }\n        }\n\n        return $controllers;\n    }\n\n    /**\n     * Add a controller to the collection if it does not exist. If the\n     * controller implements an interface suffixed with \"Docs\" it\n     * will be used instead of the controller.\n     *\n     * @param \\Illuminate\\Support\\Collection $controllers\n     * @param object                         $controller\n     *\n     * @return void\n     */\n    protected function addControllerIfNotExists(Collection $controllers, $controller)\n    {\n        $class = get_class($controller);\n\n        if ($controllers->has($class)) {\n            return;\n        }\n\n        $reflection = new ReflectionClass($controller);\n\n        $interface = Arr::first($reflection->getInterfaces(), function ($key, $value) {\n            return Str::endsWith($key, 'Docs');\n        });\n\n        if ($interface) {\n            $controller = $interface;\n        }\n\n        $controllers->put($class, $controller);\n    }\n}\n"
  },
  {
    "path": "src/Console/Command/Routes.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Console\\Command;\n\nuse Illuminate\\Support\\Arr;\nuse Illuminate\\Support\\Str;\nuse Dingo\\Api\\Routing\\Router;\nuse Illuminate\\Console\\Command;\nuse Symfony\\Component\\Console\\Input\\InputOption;\nuse Illuminate\\Foundation\\Console\\RouteListCommand;\n\nclass Routes extends RouteListCommand\n{\n    /**\n     * Dingo router instance.\n     *\n     * @var \\Dingo\\Api\\Routing\\Router\n     */\n    protected $router;\n\n    /**\n     * Array of route collections.\n     *\n     * @var array\n     */\n    protected $routes;\n\n    /**\n     * The console command name.\n     *\n     * @var string\n     */\n    protected $name = 'api:routes';\n\n    /**\n     * The console command description.\n     *\n     * @var string\n     */\n    protected $description = 'List all registered API routes';\n\n    /**\n     * The table headers for the command.\n     *\n     * @var array\n     */\n    protected $headers = ['Host', 'Method', 'URI', 'Name', 'Action', 'Protected', 'Version(s)', 'Scope(s)', 'Rate Limit'];\n\n    /**\n     * Create a new routes command instance.\n     *\n     * @param \\Dingo\\Api\\Routing\\Router $router\n     *\n     * @return void\n     */\n    public function __construct(Router $router)\n    {\n        // Ugly, but we need to bypass the constructor and directly target the\n        // constructor on the command class.\n        Command::__construct();\n\n        $this->router = $router;\n    }\n\n    /**\n     * Execute the console command.\n     *\n     * @return void\n     */\n    public function fire()\n    {\n        $this->routes = $this->router->getRoutes();\n\n        parent::fire();\n    }\n\n    /**\n     * Execute the console command.\n     *\n     * @return void\n     */\n    public function handle()\n    {\n        $this->routes = $this->router->getRoutes();\n\n        parent::handle();\n    }\n\n    /**\n     * Compile the routes into a displayable format.\n     *\n     * @return array\n     */\n    protected function getRoutes()\n    {\n        $routes = [];\n\n        foreach ($this->router->getRoutes() as $collection) {\n            foreach ($collection->getRoutes() as $route) {\n                $routes[] = $this->filterRoute([\n                    'host' => $route->domain(),\n                    'method' => implode('|', $route->methods()),\n                    'uri' => $route->uri(),\n                    'name' => $route->getName(),\n                    'action' => $route->getActionName(),\n                    'protected' => $route->isProtected() ? 'Yes' : 'No',\n                    'versions' => implode(', ', $route->versions()),\n                    'scopes' => implode(', ', $route->scopes()),\n                    'rate' => $this->routeRateLimit($route),\n                ]);\n            }\n        }\n\n        if ($sort = $this->option('sort')) {\n            $routes = Arr::sort($routes, function ($value) use ($sort) {\n                return $value[$sort];\n            });\n        }\n\n        if ($this->option('reverse')) {\n            $routes = array_reverse($routes);\n        }\n\n        if ($this->option('short')) {\n            $this->headers = ['Method', 'URI', 'Name', 'Version(s)'];\n\n            $routes = array_map(function ($item) {\n                return Arr::only($item, ['method', 'uri', 'name', 'versions']);\n            }, $routes);\n        }\n\n        return array_filter(array_unique($routes, SORT_REGULAR));\n    }\n\n    /**\n     * Display the routes rate limiting requests per second. This takes the limit\n     * and divides it by the expiration time in seconds to give you a rough\n     * idea of how many requests you'd be able to fire off per second\n     * on the route.\n     *\n     * @param \\Dingo\\Api\\Routing\\Route $route\n     *\n     * @return null|string\n     */\n    protected function routeRateLimit($route)\n    {\n        [$limit, $expires] = [$route->getRateLimit(), $route->getRateLimitExpiration()];\n\n        if ($limit && $expires) {\n            return sprintf('%s req/s', round($limit / ($expires * 60), 2));\n        }\n    }\n\n    /**\n     * Filter the route by URI, Version, Scopes and / or name.\n     *\n     * @param array $route\n     *\n     * @return array|null\n     */\n    protected function filterRoute(array $route)\n    {\n        $filters = ['name', 'path', 'protected', 'unprotected', 'versions', 'scopes'];\n\n        foreach ($filters as $filter) {\n            if ($this->option($filter) && ! $this->{'filterBy'.ucfirst($filter)}($route)) {\n                return;\n            }\n        }\n\n        return $route;\n    }\n\n    /**\n     * Get the console command options.\n     *\n     * @return array\n     */\n    protected function getOptions()\n    {\n        $options = parent::getOptions();\n\n        foreach ($options as $key => $option) {\n            if ($option[0] == 'sort') {\n                unset($options[$key]);\n            }\n        }\n\n        return array_merge(\n            $options,\n            [\n                ['sort', null, InputOption::VALUE_OPTIONAL, 'The column (domain, method, uri, name, action) to sort by'],\n                ['versions', null, InputOption::VALUE_IS_ARRAY | InputOption::VALUE_OPTIONAL, 'Filter the routes by version'],\n                ['scopes', 'S', InputOption::VALUE_IS_ARRAY | InputOption::VALUE_OPTIONAL, 'Filter the routes by scopes'],\n                ['protected', null, InputOption::VALUE_NONE, 'Filter the protected routes'],\n                ['unprotected', null, InputOption::VALUE_NONE, 'Filter the unprotected routes'],\n                ['short', null, InputOption::VALUE_NONE, 'Get an abridged version of the routes'],\n            ]\n        );\n    }\n\n    /**\n     * Filter the route by its path.\n     *\n     * @param array $route\n     *\n     * @return bool\n     */\n    protected function filterByPath(array $route)\n    {\n        return Str::contains($route['uri'], $this->option('path'));\n    }\n\n    /**\n     * Filter the route by whether or not it is protected.\n     *\n     * @param array $route\n     *\n     * @return bool\n     */\n    protected function filterByProtected(array $route)\n    {\n        return $this->option('protected') && $route['protected'] == 'Yes';\n    }\n\n    /**\n     * Filter the route by whether or not it is unprotected.\n     *\n     * @param array $route\n     *\n     * @return bool\n     */\n    protected function filterByUnprotected(array $route)\n    {\n        return $this->option('unprotected') && $route['protected'] == 'No';\n    }\n\n    /**\n     * Filter the route by its versions.\n     *\n     * @param array $route\n     *\n     * @return bool\n     */\n    protected function filterByVersions(array $route)\n    {\n        foreach ($this->option('versions') as $version) {\n            if (Str::contains($route['versions'], $version)) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    /**\n     * Filter the route by its name.\n     *\n     * @param array $route\n     *\n     * @return bool\n     */\n    protected function filterByName(array $route)\n    {\n        return Str::contains($route['name'], $this->option('name'));\n    }\n\n    /**\n     * Filter the route by its scopes.\n     *\n     * @param array $route\n     *\n     * @return bool\n     */\n    protected function filterByScopes(array $route)\n    {\n        foreach ($this->option('scopes') as $scope) {\n            if (Str::contains($route['scopes'], $scope)) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n}\n"
  },
  {
    "path": "src/Contract/Auth/Provider.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Contract\\Auth;\n\nuse Dingo\\Api\\Routing\\Route;\nuse Illuminate\\Http\\Request;\n\ninterface Provider\n{\n    /**\n     * Authenticate the request and return the authenticated user instance.\n     *\n     * @param \\Illuminate\\Http\\Request $request\n     * @param \\Dingo\\Api\\Routing\\Route $route\n     *\n     * @return mixed\n     */\n    public function authenticate(Request $request, Route $route);\n}\n"
  },
  {
    "path": "src/Contract/Debug/ExceptionHandler.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Contract\\Debug;\n\ninterface ExceptionHandler\n{\n    /**\n     * Handle an exception.\n     *\n     * @param \\Throwable|\\Exception $exception\n     *\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function handle($exception);\n}\n"
  },
  {
    "path": "src/Contract/Debug/MessageBagErrors.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Contract\\Debug;\n\ninterface MessageBagErrors\n{\n    /**\n     * Get the errors message bag.\n     *\n     * @return \\Illuminate\\Support\\MessageBag\n     */\n    public function getErrors();\n\n    /**\n     * Determine if message bag has any errors.\n     *\n     * @return bool\n     */\n    public function hasErrors();\n}\n"
  },
  {
    "path": "src/Contract/Http/Parser.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Contract\\Http;\n\nuse Illuminate\\Http\\Request as IlluminateRequest;\n\ninterface Parser\n{\n    /**\n     * Parse an incoming request.\n     *\n     * @param \\Illuminate\\Http\\Request $request\n     *\n     * @return mixed\n     */\n    public function parse(IlluminateRequest $request);\n}\n"
  },
  {
    "path": "src/Contract/Http/RateLimit/HasRateLimiter.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Contract\\Http\\RateLimit;\n\nuse Dingo\\Api\\Http\\Request;\nuse Illuminate\\Container\\Container;\n\ninterface HasRateLimiter\n{\n    /**\n     * Get rate limiter callable.\n     *\n     * @param \\Illuminate\\Container\\Container $app\n     * @param \\Dingo\\Api\\Http\\Request         $request\n     *\n     * @return string\n     */\n    public function getRateLimiter(Container $app, Request $request);\n}\n"
  },
  {
    "path": "src/Contract/Http/RateLimit/Throttle.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Contract\\Http\\RateLimit;\n\nuse Illuminate\\Container\\Container;\n\ninterface Throttle\n{\n    /**\n     * Attempt to match the throttle against a given condition.\n     *\n     * @param \\Illuminate\\Container\\Container $container\n     *\n     * @return bool\n     */\n    public function match(Container $container);\n\n    /**\n     * Get the time in minutes that the throttles request limit will expire.\n     *\n     * @return int\n     */\n    public function getExpires();\n\n    /**\n     * Get the throttles request limit.\n     *\n     * @return int\n     */\n    public function getLimit();\n}\n"
  },
  {
    "path": "src/Contract/Http/Request.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Contract\\Http;\n\nuse Illuminate\\Http\\Request as IlluminateRequest;\n\ninterface Request\n{\n    /**\n     * Create a new Dingo request instance from an Illuminate request instance.\n     *\n     * @param \\Illuminate\\Http\\Request $old\n     *\n     * @return \\Dingo\\Api\\Http\\Request\n     */\n    public function createFromIlluminate(IlluminateRequest $old);\n}\n"
  },
  {
    "path": "src/Contract/Http/Validator.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Contract\\Http;\n\nuse Illuminate\\Http\\Request as IlluminateRequest;\n\ninterface Validator\n{\n    /**\n     * Validate a request.\n     *\n     * @param \\Illuminate\\Http\\Request $request\n     *\n     * @return bool\n     */\n    public function validate(IlluminateRequest $request);\n}\n"
  },
  {
    "path": "src/Contract/Routing/Adapter.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Contract\\Routing;\n\nuse Illuminate\\Http\\Request;\n\ninterface Adapter\n{\n    /**\n     * Dispatch a request.\n     *\n     * @param \\Illuminate\\Http\\Request $request\n     * @param string                   $version\n     *\n     * @return mixed\n     */\n    public function dispatch(Request $request, $version);\n\n    /**\n     * Get the URI, methods, and action from the route.\n     *\n     * @param mixed                    $route\n     * @param \\Illuminate\\Http\\Request $request\n     *\n     * @return array\n     */\n    public function getRouteProperties($route, Request $request);\n\n    /**\n     * Add a route to the appropriate route collection.\n     *\n     * @param array  $methods\n     * @param array  $versions\n     * @param string $uri\n     * @param mixed  $action\n     *\n     * @return void\n     */\n    public function addRoute(array $methods, array $versions, $uri, $action);\n\n    /**\n     * Get all routes or only for a specific version.\n     *\n     * @param string $version\n     *\n     * @return mixed\n     */\n    public function getRoutes($version = null);\n\n    /**\n     * Get a normalized iterable set of routes. Top level key must be a version with each\n     * version containing iterable routes that can be consumed by the adapter.\n     *\n     * @param string $version\n     *\n     * @return mixed\n     */\n    public function getIterableRoutes($version = null);\n\n    /**\n     * Set the routes on the adapter.\n     *\n     * @param array $routes\n     *\n     * @return void\n     */\n    public function setRoutes(array $routes);\n\n    /**\n     * Prepare a route for serialization.\n     *\n     * @param mixed $route\n     *\n     * @return mixed\n     */\n    public function prepareRouteForSerialization($route);\n}\n"
  },
  {
    "path": "src/Contract/Transformer/Adapter.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Contract\\Transformer;\n\nuse Dingo\\Api\\Http\\Request;\nuse Dingo\\Api\\Transformer\\Binding;\n\ninterface Adapter\n{\n    /**\n     * Transform a response with a transformer.\n     *\n     * @param mixed                          $response\n     * @param object                         $transformer\n     * @param \\Dingo\\Api\\Transformer\\Binding $binding\n     * @param \\Dingo\\Api\\Http\\Request        $request\n     *\n     * @return array\n     */\n    public function transform($response, $transformer, Binding $binding, Request $request);\n}\n"
  },
  {
    "path": "src/Dispatcher.php",
    "content": "<?php\n\nnamespace Dingo\\Api;\n\nuse Dingo\\Api\\Auth\\Auth;\nuse Illuminate\\Support\\Str;\nuse Dingo\\Api\\Routing\\Router;\nuse Dingo\\Api\\Http\\InternalRequest;\nuse Illuminate\\Container\\Container;\nuse Illuminate\\Filesystem\\Filesystem;\nuse Symfony\\Component\\HttpFoundation\\Cookie;\nuse Dingo\\Api\\Exception\\InternalHttpException;\nuse Symfony\\Component\\HttpFoundation\\File\\UploadedFile;\nuse Illuminate\\Support\\Facades\\Request as RequestFacade;\nuse Symfony\\Component\\HttpKernel\\Exception\\HttpExceptionInterface;\n\nclass Dispatcher\n{\n    /**\n     * Illuminate container instance.\n     *\n     * @var \\Illuminate\\Container\\Container\n     */\n    protected $container;\n\n    /**\n     * Illuminate filesystem instance.\n     *\n     * @var \\Illuminate\\Filesystem\\Filesystem\n     */\n    protected $files;\n\n    /**\n     * Router instance.\n     *\n     * @var \\Dingo\\Api\\Routing\\Router\n     */\n    protected $router;\n\n    /**\n     * Auth instance.\n     *\n     * @var \\Dingo\\Api\\Auth\\Auth\n     */\n    protected $auth;\n\n    /**\n     * Internal request stack.\n     *\n     * @var array\n     */\n    protected $requestStack = [];\n\n    /**\n     * Internal route stack.\n     *\n     * @var array\n     */\n    protected $routeStack = [];\n\n    /**\n     * Version for the request.\n     *\n     * @var string\n     */\n    protected $version;\n\n    /**\n     * Request headers.\n     *\n     * @var array\n     */\n    protected $headers = [];\n\n    /**\n     * Request cookies.\n     *\n     * @var array\n     */\n    protected $cookies = [];\n\n    /**\n     * Request parameters.\n     *\n     * @var array\n     */\n    protected $parameters = [];\n\n    /**\n     * Request raw content.\n     *\n     * @var string\n     */\n    protected $content;\n\n    /**\n     * Request uploaded files.\n     *\n     * @var array\n     */\n    protected $uploads = [];\n\n    /**\n     * Domain for the request.\n     *\n     * @var string\n     */\n    protected $domain;\n\n    /**\n     * Indicates whether the returned response is the raw response object.\n     *\n     * @var bool\n     */\n    protected $raw = false;\n\n    /**\n     * Indicates whether authentication is persisted.\n     *\n     * @var bool\n     */\n    protected $persistAuthentication = true;\n\n    /**\n     * API subtype.\n     *\n     * @var string\n     */\n    protected $subtype;\n\n    /**\n     * API standards tree.\n     *\n     * @var string\n     */\n    protected $standardsTree;\n\n    /**\n     * API prefix.\n     *\n     * @var string\n     */\n    protected $prefix;\n\n    /**\n     * Default version.\n     *\n     * @var string\n     */\n    protected $defaultVersion;\n\n    /**\n     * Default domain.\n     *\n     * @var string\n     */\n    protected $defaultDomain;\n\n    /**\n     * Default format.\n     *\n     * @var string\n     */\n    protected $defaultFormat;\n\n    /**\n     * Create a new dispatcher instance.\n     *\n     * @param \\Illuminate\\Container\\Container   $container\n     * @param \\Illuminate\\Filesystem\\Filesystem $files\n     * @param \\Dingo\\Api\\Routing\\Router         $router\n     * @param \\Dingo\\Api\\Auth\\Auth              $auth\n     *\n     * @return void\n     */\n    public function __construct(Container $container, Filesystem $files, Router $router, Auth $auth)\n    {\n        $this->container = $container;\n        $this->files = $files;\n        $this->router = $router;\n        $this->auth = $auth;\n\n        $this->setupRequestStack();\n    }\n\n    /**\n     * Setup the request stack by grabbing the initial request.\n     *\n     * @return void\n     */\n    protected function setupRequestStack()\n    {\n        $this->requestStack[] = $this->container['request'];\n    }\n\n    /**\n     * Attach files to be uploaded.\n     *\n     * @param array $files\n     *\n     * @return \\Dingo\\Api\\Dispatcher\n     */\n    public function attach(array $files)\n    {\n        foreach ($files as $key => $file) {\n            if (is_array($file)) {\n                $file = new UploadedFile($file['path'], basename($file['path']), $file['mime'], $file['size']);\n            } elseif (is_string($file)) {\n                $finfo = finfo_open(FILEINFO_MIME_TYPE);\n\n                $file = new UploadedFile($file, basename($file), finfo_file($finfo, $file), $this->files->size($file));\n            } elseif (! $file instanceof UploadedFile) {\n                continue;\n            }\n\n            $this->uploads[$key] = $file;\n        }\n\n        return $this;\n    }\n\n    /**\n     * Internal request will be authenticated as the given user.\n     *\n     * @param mixed $user\n     *\n     * @return \\Dingo\\Api\\Dispatcher\n     */\n    public function be($user)\n    {\n        $this->auth->setUser($user);\n\n        return $this;\n    }\n\n    /**\n     * Send a JSON payload in the request body.\n     *\n     * @param string|array $content\n     *\n     * @return \\Dingo\\Api\\Dispatcher\n     */\n    public function json($content)\n    {\n        if (is_array($content)) {\n            $content = json_encode($content);\n        }\n\n        $this->content = $content;\n\n        return $this->header('Content-Type', 'application/json');\n    }\n\n    /**\n     * Sets the domain to be used for the request.\n     *\n     * @param string $domain\n     *\n     * @return \\Dingo\\Api\\Dispatcher\n     */\n    public function on($domain)\n    {\n        $this->domain = $domain;\n\n        return $this;\n    }\n\n    /**\n     * Return the raw response object once request is dispatched.\n     *\n     * @return \\Dingo\\Api\\Dispatcher\n     */\n    public function raw()\n    {\n        $this->raw = true;\n\n        return $this;\n    }\n\n    /**\n     * Only authenticate with the given user for a single request.\n     *\n     * @return \\Dingo\\Api\\Dispatcher\n     */\n    public function once()\n    {\n        $this->persistAuthentication = false;\n\n        return $this;\n    }\n\n    /**\n     * Set the version of the API for the next request.\n     *\n     * @param string $version\n     *\n     * @return \\Dingo\\Api\\Dispatcher\n     */\n    public function version($version)\n    {\n        $this->version = $version;\n\n        return $this;\n    }\n\n    /**\n     * Set the parameters to be sent on the next API request.\n     *\n     * @param string|array $parameters\n     *\n     * @return \\Dingo\\Api\\Dispatcher\n     */\n    public function with($parameters)\n    {\n        $this->parameters = array_merge($this->parameters, is_array($parameters) ? $parameters : func_get_args());\n\n        return $this;\n    }\n\n    /**\n     * Set a header to be sent on the next API request.\n     *\n     * @param string $key\n     * @param string $value\n     *\n     * @return \\Dingo\\Api\\Dispatcher\n     */\n    public function header($key, $value)\n    {\n        $this->headers[$key] = $value;\n\n        return $this;\n    }\n\n    /**\n     * Set a cookie to be sent on the next API request.\n     *\n     * @param \\Symfony\\Component\\HttpFoundation\\Cookie $cookie\n     *\n     * @return \\Dingo\\Api\\Dispatcher\n     */\n    public function cookie(Cookie $cookie)\n    {\n        $this->cookies[] = $cookie;\n\n        return $this;\n    }\n\n    /**\n     * Perform API GET request.\n     *\n     * @param string       $uri\n     * @param string|array $parameters\n     *\n     * @return mixed\n     */\n    public function get($uri, $parameters = [])\n    {\n        return $this->queueRequest('get', $uri, $parameters);\n    }\n\n    /**\n     * Perform API POST request.\n     *\n     * @param string       $uri\n     * @param string|array $parameters\n     * @param string       $content\n     *\n     * @return mixed\n     */\n    public function post($uri, $parameters = [], $content = '')\n    {\n        return $this->queueRequest('post', $uri, $parameters, $content);\n    }\n\n    /**\n     * Perform API PUT request.\n     *\n     * @param string       $uri\n     * @param string|array $parameters\n     * @param string       $content\n     *\n     * @return mixed\n     */\n    public function put($uri, $parameters = [], $content = '')\n    {\n        return $this->queueRequest('put', $uri, $parameters, $content);\n    }\n\n    /**\n     * Perform API PATCH request.\n     *\n     * @param string       $uri\n     * @param string|array $parameters\n     * @param string       $content\n     *\n     * @return mixed\n     */\n    public function patch($uri, $parameters = [], $content = '')\n    {\n        return $this->queueRequest('patch', $uri, $parameters, $content);\n    }\n\n    /**\n     * Perform API DELETE request.\n     *\n     * @param string       $uri\n     * @param string|array $parameters\n     * @param string       $content\n     *\n     * @return mixed\n     */\n    public function delete($uri, $parameters = [], $content = '')\n    {\n        return $this->queueRequest('delete', $uri, $parameters, $content);\n    }\n\n    /**\n     * Queue up and dispatch a new request.\n     *\n     * @param string       $verb\n     * @param string       $uri\n     * @param string|array $parameters\n     * @param string       $content\n     *\n     * @return mixed\n     */\n    protected function queueRequest($verb, $uri, $parameters, $content = '')\n    {\n        if (! empty($content)) {\n            $this->content = $content;\n        }\n\n        // Sometimes after setting the initial request another request might be made prior to\n        // internally dispatching an API request. We need to capture this request as well\n        // and add it to the request stack as it has become the new parent request to\n        // this internal request. This will generally occur during tests when\n        // using the crawler to navigate pages that also make internal\n        // requests.\n        if (end($this->requestStack) != $this->container['request']) {\n            $this->requestStack[] = $this->container['request'];\n        }\n\n        $this->requestStack[] = $request = $this->createRequest($verb, $uri, $parameters);\n\n        return $this->dispatch($request);\n    }\n\n    /**\n     * Create a new internal request from an HTTP verb and URI.\n     *\n     * @param string       $verb\n     * @param string       $uri\n     * @param string|array $parameters\n     *\n     * @return \\Dingo\\Api\\Http\\InternalRequest\n     */\n    protected function createRequest($verb, $uri, $parameters)\n    {\n        $parameters = array_merge($this->parameters, (array) $parameters);\n\n        $uri = $this->addPrefixToUri($uri);\n\n        // If the URI does not have a scheme then we can assume that there it is not an\n        // absolute URI, in this case we'll prefix the root requests path to the URI.\n        $rootUrl = $this->getRootRequest()->root();\n        if ((! parse_url($uri, PHP_URL_SCHEME)) && parse_url($rootUrl) !== false) {\n            $uri = rtrim($rootUrl, '/').'/'.ltrim($uri, '/');\n        }\n\n        $request = InternalRequest::create(\n            $uri,\n            $verb,\n            $parameters,\n            $this->cookies,\n            $this->uploads,\n            $this->container['request']->server->all(),\n            $this->content\n        );\n\n        $request->headers->set('host', $this->getDomain());\n\n        foreach ($this->headers as $header => $value) {\n            $request->headers->set($header, $value);\n        }\n\n        $request->headers->set('accept', $this->getAcceptHeader());\n\n        return $request;\n    }\n\n    /**\n     * Add the prefix to the URI.\n     *\n     * @param string $uri\n     *\n     * @return string\n     */\n    protected function addPrefixToUri($uri)\n    {\n        if (! isset($this->prefix)) {\n            return $uri;\n        }\n\n        $uri = trim($uri, '/');\n\n        if (Str::startsWith($uri, $this->prefix)) {\n            return $uri;\n        }\n\n        return rtrim('/'.trim($this->prefix, '/').'/'.$uri, '/');\n    }\n\n    /**\n     * Build the \"Accept\" header.\n     *\n     * @return string\n     */\n    protected function getAcceptHeader()\n    {\n        return sprintf('application/%s.%s.%s+%s', $this->getStandardsTree(), $this->getSubtype(), $this->getVersion(), $this->getFormat());\n    }\n\n    /**\n     * Attempt to dispatch an internal request.\n     *\n     * @param \\Dingo\\Api\\Http\\InternalRequest $request\n     *\n     * @throws \\Exception|\\Symfony\\Component\\HttpKernel\\Exception\\HttpExceptionInterface\n     *\n     * @return mixed\n     */\n    protected function dispatch(InternalRequest $request)\n    {\n        $this->routeStack[] = $this->router->getCurrentRoute();\n\n        $this->clearCachedFacadeInstance();\n\n        try {\n            $this->container->instance('request', $request);\n\n            $response = $this->router->dispatch($request);\n\n            if (! $response->isSuccessful() && ! $response->isRedirection()) {\n                throw new InternalHttpException($response);\n            }\n\n            if (! $this->raw) {\n                $response = $response->getOriginalContent();\n            }\n        } catch (HttpExceptionInterface $exception) {\n            $this->refreshRequestStack();\n\n            throw $exception;\n        }\n\n        $this->refreshRequestStack();\n\n        return $response;\n    }\n\n    /**\n     * Refresh the request stack.\n     *\n     * This is done by resetting the authentication, popping\n     * the last request from the stack, replacing the input,\n     * and resetting the version and parameters.\n     *\n     * @return void\n     */\n    protected function refreshRequestStack()\n    {\n        if (! $this->persistAuthentication) {\n            $this->auth->setUser(null);\n\n            $this->persistAuthentication = true;\n        }\n\n        if ($route = array_pop($this->routeStack)) {\n            $this->router->setCurrentRoute($route);\n        }\n\n        $this->replaceRequestInstance();\n\n        $this->clearCachedFacadeInstance();\n\n        $this->raw = false;\n\n        $this->version = $this->domain = $this->content = null;\n\n        $this->parameters = $this->uploads = [];\n    }\n\n    /**\n     * Replace the request instance with the previous request instance.\n     *\n     * @return void\n     */\n    protected function replaceRequestInstance()\n    {\n        array_pop($this->requestStack);\n\n        $this->container->instance('request', end($this->requestStack));\n    }\n\n    /**\n     * Clear the cached facade instance.\n     *\n     * @return void\n     */\n    protected function clearCachedFacadeInstance()\n    {\n        // Facades cache the resolved instance so we need to clear out the\n        // request instance that may have been cached. Otherwise we'll\n        // may get unexpected results.\n        RequestFacade::clearResolvedInstance('request');\n    }\n\n    /**\n     * Get the root request instance.\n     *\n     * @return \\Illuminate\\Http\\Request\n     */\n    protected function getRootRequest()\n    {\n        return reset($this->requestStack);\n    }\n\n    /**\n     * Get the domain.\n     *\n     * @return string\n     */\n    public function getDomain()\n    {\n        return $this->domain ?: $this->defaultDomain;\n    }\n\n    /**\n     * Get the version.\n     *\n     * @return string\n     */\n    public function getVersion()\n    {\n        return $this->version ?: $this->defaultVersion;\n    }\n\n    /**\n     * Get the format.\n     *\n     * @return string\n     */\n    public function getFormat()\n    {\n        return $this->defaultFormat;\n    }\n\n    /**\n     * Get the subtype.\n     *\n     * @return string\n     */\n    public function getSubtype()\n    {\n        return $this->subtype;\n    }\n\n    /**\n     * Set the subtype.\n     *\n     * @param string $subtype\n     *\n     * @return void\n     */\n    public function setSubtype($subtype)\n    {\n        $this->subtype = $subtype;\n    }\n\n    /**\n     * Get the standards tree.\n     *\n     * @return string\n     */\n    public function getStandardsTree()\n    {\n        return $this->standardsTree;\n    }\n\n    /**\n     * Set the standards tree.\n     *\n     * @param string $standardsTree\n     *\n     * @return void\n     */\n    public function setStandardsTree($standardsTree)\n    {\n        $this->standardsTree = $standardsTree;\n    }\n\n    /**\n     * Set the prefix.\n     *\n     * @param string $prefix\n     *\n     * @return void\n     */\n    public function setPrefix($prefix)\n    {\n        $this->prefix = $prefix;\n    }\n\n    /**\n     * Set the default version.\n     *\n     * @param string $version\n     *\n     * @return void\n     */\n    public function setDefaultVersion($version)\n    {\n        $this->defaultVersion = $version;\n    }\n\n    /**\n     * Set the default domain.\n     *\n     * @param string $domain\n     *\n     * @return void\n     */\n    public function setDefaultDomain($domain)\n    {\n        $this->defaultDomain = $domain;\n    }\n\n    /**\n     * Set the default format.\n     *\n     * @param string $format\n     *\n     * @return void\n     */\n    public function setDefaultFormat($format)\n    {\n        $this->defaultFormat = $format;\n    }\n}\n"
  },
  {
    "path": "src/Event/RequestWasMatched.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Event;\n\nuse Dingo\\Api\\Http\\Request;\nuse Illuminate\\Contracts\\Container\\Container;\n\nclass RequestWasMatched\n{\n    /**\n     * Request instance.\n     *\n     * @var \\Dingo\\Api\\Http\\Request\n     */\n    public $request;\n\n    /**\n     * Application instance.\n     *\n     * @var \\Illuminate\\Contracts\\Container\\Container\n     */\n    public $app;\n\n    /**\n     * Create a new request was matched event.\n     *\n     * @param \\Dingo\\Api\\Http\\Request                   $request\n     * @param \\Illuminate\\Contracts\\Container\\Container $app\n     *\n     * @return void\n     */\n    public function __construct(Request $request, Container $app)\n    {\n        $this->request = $request;\n        $this->app = $app;\n    }\n}\n"
  },
  {
    "path": "src/Event/ResponseIsMorphing.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Event;\n\nuse Dingo\\Api\\Http\\Response;\n\nclass ResponseIsMorphing\n{\n    /**\n     * Response instance.\n     *\n     * @var \\Dingo\\Api\\Http\\Response\n     */\n    public $response;\n\n    /**\n     * Response content.\n     *\n     * @var string\n     */\n    public $content;\n\n    /**\n     * Create a new response is morphing event. Content is passed by reference\n     * so that multiple listeners can modify content.\n     *\n     * @param \\Dingo\\Api\\Http\\Response $response\n     * @param string                   $content\n     *\n     * @return void\n     */\n    public function __construct(Response $response, &$content)\n    {\n        $this->response = $response;\n        $this->content = &$content;\n    }\n}\n"
  },
  {
    "path": "src/Event/ResponseWasMorphed.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Event;\n\nclass ResponseWasMorphed extends ResponseIsMorphing\n{\n    //\n}\n"
  },
  {
    "path": "src/Exception/DeleteResourceFailedException.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Exception;\n\nclass DeleteResourceFailedException extends ResourceException\n{\n    //\n}\n"
  },
  {
    "path": "src/Exception/Handler.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Exception;\n\nuse Dingo\\Api\\Http\\Request;\nuse Exception;\nuse Illuminate\\Database\\Eloquent\\ModelNotFoundException;\nuse Illuminate\\Support\\Str;\nuse Illuminate\\Http\\Response;\nuse Dingo\\Api\\Contract\\Debug\\ExceptionHandler;\nuse Dingo\\Api\\Contract\\Debug\\MessageBagErrors;\nuse Illuminate\\Contracts\\Debug\\ExceptionHandler as IlluminateExceptionHandler;\nuse Illuminate\\Validation\\ValidationException;\nuse ReflectionFunction;\nuse Symfony\\Component\\Console\\Output\\OutputInterface;\nuse Symfony\\Component\\HttpFoundation\\Response as BaseResponse;\nuse Symfony\\Component\\HttpKernel\\Exception\\HttpExceptionInterface;\nuse Symfony\\Component\\HttpKernel\\Exception\\NotFoundHttpException;\nuse Throwable;\n\nclass Handler implements ExceptionHandler, IlluminateExceptionHandler\n{\n    /**\n     * Array of exception handlers.\n     *\n     * @var array\n     */\n    protected $handlers = [];\n\n    /**\n     * Generic response format.\n     *\n     * @var array\n     */\n    protected $format;\n\n    /**\n     * Indicates if we are in debug mode.\n     *\n     * @var bool\n     */\n    protected $debug = false;\n\n    /**\n     * User defined replacements to merge with defaults.\n     *\n     * @var array\n     */\n    protected $replacements = [];\n\n    /**\n     * The parent Illuminate exception handler instance.\n     *\n     * @var IlluminateExceptionHandler\n     */\n    protected $parentHandler;\n\n    /**\n     * Create a new exception handler instance.\n     *\n     * @param IlluminateExceptionHandler $parentHandler\n     * @param array                                        $format\n     * @param bool                                         $debug\n     *\n     * @return void\n     */\n    public function __construct(IlluminateExceptionHandler $parentHandler, array $format, $debug)\n    {\n        $this->parentHandler = $parentHandler;\n        $this->format = $format;\n        $this->debug = $debug;\n    }\n\n    /**\n     * Report or log an exception.\n     *\n     * @param Throwable $exception\n     *\n     * @return void\n     */\n    public function report(Throwable $throwable)\n    {\n        $this->parentHandler->report($throwable);\n    }\n\n    /**\n     * Determine if the exception should be reported.\n     *\n     * @param Throwable $e\n     *\n     * @return bool\n     */\n    public function shouldReport(Throwable $e)\n    {\n        return true;\n    }\n\n    /**\n     * Render an exception into an HTTP response.\n     *\n     * @param Request $request\n     * @param Throwable $exception\n     *\n     * @throws Exception\n     *\n     * @return mixed\n     */\n    public function render($request, Throwable $exception)\n    {\n        return $this->handle($exception);\n    }\n\n    /**\n     * Render an exception to the console.\n     *\n     * @param OutputInterface $output\n     * @param Throwable $exception\n     *\n     * @return mixed\n     */\n    public function renderForConsole($output, Throwable $exception)\n    {\n        return $this->parentHandler->renderForConsole($output, $exception);\n    }\n\n    /**\n     * Register a new exception handler.\n     *\n     * @param callable $callback\n     *\n     * @return void\n     */\n    public function register(callable $callback)\n    {\n        $hint = $this->handlerHint($callback);\n\n        $this->handlers[$hint] = $callback;\n    }\n\n    /**\n     * Handle an exception if it has an existing handler.\n     *\n     * @param Throwable|Exception $exception\n     *\n     * @return Response\n     */\n    public function handle($exception)\n    {\n        // Convert Eloquent's 500 ModelNotFoundException into a 404 NotFoundHttpException\n        if ($exception instanceof ModelNotFoundException) {\n            $exception = new NotFoundHttpException($exception->getMessage(), $exception);\n        }\n\n        foreach ($this->handlers as $hint => $handler) {\n            if (! $exception instanceof $hint) {\n                continue;\n            }\n\n            if ($response = $handler($exception)) {\n                if (! $response instanceof BaseResponse) {\n                    $response = new Response($response, $this->getExceptionStatusCode($exception));\n                }\n\n                return $response->withException($exception);\n            }\n        }\n\n        return $this->genericResponse($exception)->withException($exception);\n    }\n\n    /**\n     * Handle a generic error response if there is no handler available.\n     *\n     * @param Throwable $exception\n     *\n     * @throws Throwable\n     *\n     * @return Response\n     */\n    protected function genericResponse(Throwable $exception)\n    {\n        $replacements = $this->prepareReplacements($exception);\n\n        $response = $this->newResponseArray();\n\n        array_walk_recursive($response, function (&$value, $key) use ($replacements) {\n            if (Str::startsWith($value, ':') && isset($replacements[$value])) {\n                $value = $replacements[$value];\n            }\n        });\n\n        $response = $this->recursivelyRemoveEmptyReplacements($response);\n\n        return new Response($response, $this->getStatusCode($exception), $this->getHeaders($exception));\n    }\n\n    /**\n     * Get the status code from the exception.\n     *\n     * @param Throwable $exception\n     *\n     * @return int\n     */\n    protected function getStatusCode(Throwable $exception)\n    {\n        $statusCode = null;\n\n        if ($exception instanceof ValidationException) {\n            $statusCode = $exception->status;\n        } elseif ($exception instanceof HttpExceptionInterface) {\n            $statusCode = $exception->getStatusCode();\n        } else {\n            // By default throw 500\n            $statusCode = 500;\n        }\n\n        // Be extra defensive\n        if ($statusCode < 100 || $statusCode > 599) {\n            $statusCode = 500;\n        }\n\n        return $statusCode;\n    }\n\n    /**\n     * Get the headers from the exception.\n     *\n     * @param Throwable $exception\n     *\n     * @return array\n     */\n    protected function getHeaders(Throwable $exception)\n    {\n        return $exception instanceof HttpExceptionInterface ? $exception->getHeaders() : [];\n    }\n\n    /**\n     * Prepare the replacements array by gathering the keys and values.\n     *\n     * @param Throwable $exception\n     *\n     * @return array\n     */\n    protected function prepareReplacements(Throwable $exception)\n    {\n        $statusCode = $this->getStatusCode($exception);\n\n        if (! $message = $exception->getMessage()) {\n            $message = sprintf('%d %s', $statusCode, Response::$statusTexts[$statusCode]);\n        }\n\n        $replacements = [\n            ':message' => $message,\n            ':status_code' => $statusCode,\n        ];\n\n        if ($exception instanceof MessageBagErrors && $exception->hasErrors()) {\n            $replacements[':errors'] = $exception->getErrors();\n        }\n\n        if ($exception instanceof ValidationException) {\n            $replacements[':errors'] = $exception->errors();\n            $replacements[':status_code'] = $exception->status;\n        }\n\n        if ($code = $exception->getCode()) {\n            $replacements[':code'] = $code;\n        }\n\n        if ($this->runningInDebugMode()) {\n            $replacements[':debug'] = [\n                'line' => $exception->getLine(),\n                'file' => $exception->getFile(),\n                'class' => get_class($exception),\n                'trace' => explode(\"\\n\", $exception->getTraceAsString()),\n            ];\n\n            // Attach trace of previous exception, if exists\n            if (! is_null($exception->getPrevious())) {\n                $currentTrace = $replacements[':debug']['trace'];\n\n                $replacements[':debug']['trace'] = [\n                    'previous' => explode(\"\\n\", $exception->getPrevious()->getTraceAsString()),\n                    'current' => $currentTrace,\n                ];\n            }\n        }\n\n        return array_merge($replacements, $this->replacements);\n    }\n\n    /**\n     * Set user defined replacements.\n     *\n     * @param array $replacements\n     *\n     * @return void\n     */\n    public function setReplacements(array $replacements)\n    {\n        $this->replacements = $replacements;\n    }\n\n    /**\n     * Recursively remove any empty replacement values in the response array.\n     *\n     * @param array $input\n     *\n     * @return array\n     */\n    protected function recursivelyRemoveEmptyReplacements(array $input)\n    {\n        foreach ($input as &$value) {\n            if (is_array($value)) {\n                $value = $this->recursivelyRemoveEmptyReplacements($value);\n            }\n        }\n\n        return array_filter($input, function ($value) {\n            if (is_string($value)) {\n                return ! Str::startsWith($value, ':');\n            }\n\n            return true;\n        });\n    }\n\n    /**\n     * Create a new response array with replacement values.\n     *\n     * @return array\n     */\n    protected function newResponseArray()\n    {\n        return $this->format;\n    }\n\n    /**\n     * Get the exception status code.\n     *\n     * @param Exception $exception\n     * @param int        $defaultStatusCode\n     *\n     * @return int\n     */\n    protected function getExceptionStatusCode(Exception $exception, $defaultStatusCode = 500)\n    {\n        return ($exception instanceof HttpExceptionInterface) ? $exception->getStatusCode() : $defaultStatusCode;\n    }\n\n    /**\n     * Determines if we are running in debug mode.\n     *\n     * @return bool\n     */\n    protected function runningInDebugMode()\n    {\n        return $this->debug;\n    }\n\n    /**\n     * Get the hint for an exception handler.\n     *\n     * @param callable $callback\n     *\n     * @return string\n     */\n    protected function handlerHint(callable $callback)\n    {\n        $reflection = new ReflectionFunction($callback);\n\n        $exception = $reflection->getParameters()[0];\n        $reflectionType = $exception->getType();\n\n        if ($reflectionType && ! $reflectionType->isBuiltin()) {\n            if ($reflectionType instanceof \\ReflectionNamedType) {\n                return $reflectionType->getName();\n            }\n        }\n\n        return '';\n    }\n\n    /**\n     * Get the exception handlers.\n     *\n     * @return array\n     */\n    public function getHandlers()\n    {\n        return $this->handlers;\n    }\n\n    /**\n     * Set the error format array.\n     *\n     * @param array $format\n     *\n     * @return void\n     */\n    public function setErrorFormat(array $format)\n    {\n        $this->format = $format;\n    }\n\n    /**\n     * Set the debug mode.\n     *\n     * @param bool $debug\n     *\n     * @return void\n     */\n    public function setDebug($debug)\n    {\n        $this->debug = $debug;\n    }\n}\n"
  },
  {
    "path": "src/Exception/InternalHttpException.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Exception;\n\nuse Exception;\nuse Symfony\\Component\\HttpFoundation\\Response;\nuse Symfony\\Component\\HttpKernel\\Exception\\HttpException;\n\nclass InternalHttpException extends HttpException\n{\n    /**\n     * The response.\n     *\n     * @var \\Illuminate\\Http\\Response\n     */\n    protected $response;\n\n    /**\n     * Create a new internal HTTP exception instance.\n     *\n     * @param \\Symfony\\Component\\HttpFoundation\\Response $response\n     * @param string                                     $message\n     * @param \\Exception                                 $previous\n     * @param array                                      $headers\n     * @param int                                        $code\n     *\n     * @return void\n     */\n    public function __construct(Response $response, $message = null, Exception $previous = null, array $headers = [], $code = 0)\n    {\n        $this->response = $response;\n\n        parent::__construct($response->getStatusCode(), $message, $previous, $headers, $code);\n    }\n\n    /**\n     * Get the response of the internal request.\n     *\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function getResponse()\n    {\n        return $this->response;\n    }\n}\n"
  },
  {
    "path": "src/Exception/RateLimitExceededException.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Exception;\n\nuse Exception;\nuse Symfony\\Component\\HttpKernel\\Exception\\HttpException;\n\nclass RateLimitExceededException extends HttpException\n{\n    /**\n     * Create a new rate limit exceeded exception instance.\n     *\n     * @param string     $message\n     * @param \\Exception $previous\n     * @param array      $headers\n     * @param int        $code\n     *\n     * @return void\n     */\n    public function __construct($message = null, Exception $previous = null, $headers = [], $code = 0)\n    {\n        if (array_key_exists('X-RateLimit-Reset', $headers)) {\n            $headers['Retry-After'] = $headers['X-RateLimit-Reset'] - time();\n        }\n\n        parent::__construct(429, $message ?: 'You have exceeded your rate limit.', $previous, $headers, $code);\n    }\n}\n"
  },
  {
    "path": "src/Exception/ResourceException.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Exception;\n\nuse Exception;\nuse Illuminate\\Support\\MessageBag;\nuse Dingo\\Api\\Contract\\Debug\\MessageBagErrors;\nuse Symfony\\Component\\HttpKernel\\Exception\\HttpException;\n\nclass ResourceException extends HttpException implements MessageBagErrors\n{\n    /**\n     * MessageBag errors.\n     *\n     * @var \\Illuminate\\Support\\MessageBag\n     */\n    protected $errors;\n\n    /**\n     * Create a new resource exception instance.\n     *\n     * @param string                               $message\n     * @param \\Illuminate\\Support\\MessageBag|array $errors\n     * @param \\Exception                           $previous\n     * @param array                                $headers\n     * @param int                                  $code\n     *\n     * @return void\n     */\n    public function __construct($message = null, $errors = null, Exception $previous = null, $headers = [], $code = 0)\n    {\n        if (is_null($errors)) {\n            $this->errors = new MessageBag;\n        } else {\n            $this->errors = is_array($errors) ? new MessageBag($errors) : $errors;\n        }\n\n        parent::__construct(422, $message, $previous, $headers, $code);\n    }\n\n    /**\n     * Get the errors message bag.\n     *\n     * @return \\Illuminate\\Support\\MessageBag\n     */\n    public function getErrors()\n    {\n        return $this->errors;\n    }\n\n    /**\n     * Determine if message bag has any errors.\n     *\n     * @return bool\n     */\n    public function hasErrors()\n    {\n        return ! $this->errors->isEmpty();\n    }\n}\n"
  },
  {
    "path": "src/Exception/StoreResourceFailedException.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Exception;\n\nclass StoreResourceFailedException extends ResourceException\n{\n    //\n}\n"
  },
  {
    "path": "src/Exception/UnknownVersionException.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Exception;\n\nuse Exception;\nuse Symfony\\Component\\HttpKernel\\Exception\\HttpException;\n\nclass UnknownVersionException extends HttpException\n{\n    /**\n     * Create a new unknown version exception instance.\n     *\n     * @param string     $message\n     * @param \\Exception $previous\n     * @param int        $code\n     *\n     * @return void\n     */\n    public function __construct($message = null, Exception $previous = null, $code = 0)\n    {\n        parent::__construct(400, $message ?: 'The version given was unknown or has no registered routes.', $previous, [], $code);\n    }\n}\n"
  },
  {
    "path": "src/Exception/UpdateResourceFailedException.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Exception;\n\nclass UpdateResourceFailedException extends ResourceException\n{\n    //\n}\n"
  },
  {
    "path": "src/Exception/ValidationHttpException.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Exception;\n\nuse Exception;\n\nclass ValidationHttpException extends ResourceException\n{\n    /**\n     * Create a new validation HTTP exception instance.\n     *\n     * @param \\Illuminate\\Support\\MessageBag|array $errors\n     * @param \\Exception                           $previous\n     * @param array                                $headers\n     * @param int                                  $code\n     *\n     * @return void\n     */\n    public function __construct($errors = null, Exception $previous = null, $headers = [], $code = 0)\n    {\n        parent::__construct(null, $errors, $previous, $headers, $code);\n    }\n}\n"
  },
  {
    "path": "src/Facade/API.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Facade;\n\nuse Dingo\\Api\\Http\\InternalRequest;\nuse Illuminate\\Support\\Facades\\Facade;\n\nclass API extends Facade\n{\n    /**\n     * Get the registered name of the component.\n     *\n     * @return string\n     */\n    protected static function getFacadeAccessor()\n    {\n        return 'api.dispatcher';\n    }\n\n    /**\n     * Bind an exception handler.\n     *\n     * @param callable $callback\n     *\n     * @return void\n     */\n    public static function error(callable $callback)\n    {\n        return static::$app['api.exception']->register($callback);\n    }\n\n    /**\n     * Register a class transformer.\n     *\n     * @param string          $class\n     * @param string|\\Closure $transformer\n     *\n     * @return \\Dingo\\Api\\Transformer\\Binding\n     */\n    public static function transform($class, $transformer)\n    {\n        return static::$app['api.transformer']->register($class, $transformer);\n    }\n\n    /**\n     * Get the authenticator.\n     *\n     * @return \\Dingo\\Api\\Auth\\Auth\n     */\n    public static function auth()\n    {\n        return static::$app['api.auth'];\n    }\n\n    /**\n     * Get the authenticated user.\n     *\n     * @return \\Illuminate\\Auth\\GenericUser|\\Illuminate\\Database\\Eloquent\\Model\n     */\n    public static function user()\n    {\n        return static::$app['api.auth']->user();\n    }\n\n    /**\n     * Determine if a request is internal.\n     *\n     * @return bool\n     */\n    public static function internal()\n    {\n        return static::$app['api.router']->getCurrentRequest() instanceof InternalRequest;\n    }\n\n    /**\n     * Get the response factory to begin building a response.\n     *\n     * @return \\Dingo\\Api\\Http\\Response\\Factory\n     */\n    public static function response()\n    {\n        return static::$app['api.http.response'];\n    }\n\n    /**\n     * Get the API router instance.\n     *\n     * @return \\Dingo\\Api\\Routing\\Router\n     */\n    public static function router()\n    {\n        return static::$app['api.router'];\n    }\n\n    /**\n     * Get the API route of the given name, and optionally specify the API version.\n     *\n     * @param string $routeName\n     * @param string $apiVersion\n     *\n     * @return string\n     */\n    public static function route($routeName, $apiVersion = 'v1')\n    {\n        return static::$app['api.url']->version($apiVersion)->route($routeName);\n    }\n}\n"
  },
  {
    "path": "src/Facade/Route.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Facade;\n\nuse Illuminate\\Support\\Facades\\Facade;\n\nclass Route extends Facade\n{\n    /**\n     * Get the registered name of the component.\n     *\n     * @return string\n     */\n    protected static function getFacadeAccessor()\n    {\n        return 'api.router';\n    }\n}\n"
  },
  {
    "path": "src/Http/FormRequest.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Http;\n\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Http\\JsonResponse;\nuse Illuminate\\Contracts\\Container\\Container;\nuse Illuminate\\Contracts\\Validation\\Validator;\nuse Dingo\\Api\\Exception\\ValidationHttpException;\nuse Illuminate\\Validation\\ValidatesWhenResolvedTrait;\nuse Symfony\\Component\\HttpKernel\\Exception\\HttpException;\nuse Illuminate\\Contracts\\Validation\\ValidatesWhenResolved;\nuse Illuminate\\Contracts\\Validation\\Factory as ValidationFactory;\nuse Symfony\\Component\\HttpKernel\\Exception\\AccessDeniedHttpException;\n\nclass FormRequest extends Request implements ValidatesWhenResolved\n{\n    use ValidatesWhenResolvedTrait;\n\n    /**\n     * The container instance.\n     *\n     * @var \\Illuminate\\Contracts\\Container\\Container\n     */\n    protected $container;\n\n    /**\n     * The redirector instance.\n     *\n     * @var \\Illuminate\\Routing\\Redirector\n     */\n    protected $redirector;\n\n    /**\n     * The URI to redirect to if validation fails.\n     *\n     * @var string\n     */\n    protected $redirect;\n\n    /**\n     * The route to redirect to if validation fails.\n     *\n     * @var string\n     */\n    protected $redirectRoute;\n\n    /**\n     * The controller action to redirect to if validation fails.\n     *\n     * @var string\n     */\n    protected $redirectAction;\n\n    /**\n     * The key to be used for the view error bag.\n     *\n     * @var string\n     */\n    protected $errorBag = 'default';\n\n    /**\n     * The input keys that should not be flashed on redirect.\n     *\n     * @var array\n     */\n    protected $dontFlash = [\n        'password',\n        'password_confirmation',\n    ];\n\n    /**\n     * Validate the request.\n     */\n    public function validate()\n    {\n        if ($this->authorize() === false) {\n            throw new AccessDeniedHttpException();\n        }\n\n        $validator = app('validator')->make($this->all(), $this->rules(), $this->messages());\n\n        if ($validator->fails()) {\n            throw new ValidationHttpException($validator->errors());\n        }\n    }\n\n    /**\n     * Get the validator instance for the request.\n     *\n     * @return \\Illuminate\\Contracts\\Validation\\Validator\n     *\n     * @SuppressWarnings(PHPMD.ElseExpression)\n     */\n    protected function getValidatorInstance()\n    {\n        $factory = $this->container->make(ValidationFactory::class);\n\n        if (method_exists($this, 'validator')) {\n            $validator = $this->container->call([$this, 'validator'], compact('factory'));\n        } else {\n            $validator = $this->createDefaultValidator($factory);\n        }\n\n        if (method_exists($this, 'withValidator')) {\n            $this->withValidator($validator);\n        }\n\n        return $validator;\n    }\n\n    /**\n     * Create the default validator instance.\n     *\n     * @param  \\Illuminate\\Contracts\\Validation\\Factory  $factory\n     *\n     * @return \\Illuminate\\Contracts\\Validation\\Validator\n     */\n    protected function createDefaultValidator(ValidationFactory $factory)\n    {\n        return $factory->make(\n            $this->validationData(),\n            $this->container->call([$this, 'rules']),\n            $this->messages(),\n            $this->attributes()\n        );\n    }\n\n    /**\n     * Get data to be validated from the request.\n     *\n     * @return array\n     */\n    protected function validationData()\n    {\n        return $this->all();\n    }\n\n    /**\n     * Handle a failed validation attempt.\n     *\n     * @param  \\Illuminate\\Contracts\\Validation\\Validator  $validator\n     *\n     * @return void\n     */\n    protected function failedValidation(Validator $validator)\n    {\n        if ($this->container['request'] instanceof Request) {\n            throw new ValidationHttpException($validator->errors());\n        }\n\n        parent::failedValidation($validator);\n    }\n\n    /**\n     * Get the proper failed validation response for the request.\n     *\n     * @param  array  $errors\n     *\n     * @return \\Symfony\\Component\\HttpFoundation\\Response\n     */\n    public function response(array $errors)\n    {\n        if ($this->expectsJson()) {\n            return new JsonResponse($errors, 422);\n        }\n\n        return $this->redirector->to($this->getRedirectUrl())\n            ->withInput($this->except($this->dontFlash))\n            ->withErrors($errors, $this->errorBag);\n    }\n\n    /**\n     * Format the errors from the given Validator instance.\n     *\n     * @param  \\Illuminate\\Contracts\\Validation\\Validator  $validator\n     *\n     * @return array\n     */\n    protected function formatErrors(Validator $validator)\n    {\n        return $validator->getMessageBag()->toArray();\n    }\n\n    /**\n     * Get the URL to redirect to on a validation error.\n     *\n     * @return string\n     */\n    protected function getRedirectUrl()\n    {\n        $url = $this->redirector->getUrlGenerator();\n\n        if ($this->redirect) {\n            return $url->to($this->redirect);\n        } elseif ($this->redirectRoute) {\n            return $url->route($this->redirectRoute);\n        } elseif ($this->redirectAction) {\n            return $url->action($this->redirectAction);\n        }\n\n        return $url->previous();\n    }\n\n    /**\n     * Determine if the request passes the authorization check.\n     *\n     * @return bool\n     */\n    protected function passesAuthorization()\n    {\n        if (method_exists($this, 'authorize')) {\n            return $this->container->call([$this, 'authorize']);\n        }\n\n        return false;\n    }\n\n    /**\n     * Handle a failed authorization attempt.\n     *\n     * @return void\n     */\n    protected function failedAuthorization()\n    {\n        if ($this->container['request'] instanceof Request) {\n            throw new HttpException(403);\n        }\n\n        parent::failedAuthorization();\n    }\n\n    /**\n     * Get custom messages for validator errors.\n     *\n     * @return array\n     */\n    public function messages()\n    {\n        return [];\n    }\n\n    /**\n     * Get custom attributes for validator errors.\n     *\n     * @return array\n     */\n    public function attributes()\n    {\n        return [];\n    }\n\n    /**\n     * Set the Redirector instance.\n     *\n     * @param \\Laravel\\Lumen\\Http\\Redirector|\\Illuminate\\Routing\\Redirector $redirector\n     *\n     * @return $this\n     */\n    public function setRedirector($redirector)\n    {\n        $this->redirector = $redirector;\n\n        return $this;\n    }\n\n    /**\n     * Set the container implementation.\n     *\n     * @param  \\Illuminate\\Contracts\\Container\\Container  $container\n     *\n     * @return $this\n     */\n    public function setContainer(Container $container)\n    {\n        $this->container = $container;\n\n        return $this;\n    }\n}\n"
  },
  {
    "path": "src/Http/InternalRequest.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Http;\n\nclass InternalRequest extends Request\n{\n    public function __construct(array $query = [], array $request = [], array $attributes = [], array $cookies = [], array $files = [], array $server = [], $content = null)\n    {\n        parent::__construct($query, $request, $attributes, $cookies, $files, $server, $content);\n\n        // Pass parameters inside internal request into Laravel's JSON ParameterBag,\n        // so that they can be accessed using $request->input()\n        if ($this->isJson() && isset($this->request)) {\n            $this->setJson($this->request);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Http/Middleware/Auth.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Http\\Middleware;\n\nuse Closure;\nuse Dingo\\Api\\Routing\\Router;\nuse Dingo\\Api\\Auth\\Auth as Authentication;\n\nclass Auth\n{\n    /**\n     * Router instance.\n     *\n     * @var \\Dingo\\Api\\Routing\\Router\n     */\n    protected $router;\n\n    /**\n     * Authenticator instance.\n     *\n     * @var \\Dingo\\Api\\Auth\\Auth\n     */\n    protected $auth;\n\n    /**\n     * Create a new auth middleware instance.\n     *\n     * @param \\Dingo\\Api\\Routing\\Router $router\n     * @param \\Dingo\\Api\\Auth\\Auth      $auth\n     *\n     * @return void\n     */\n    public function __construct(Router $router, Authentication $auth)\n    {\n        $this->router = $router;\n        $this->auth = $auth;\n    }\n\n    /**\n     * Perform authentication before a request is executed.\n     *\n     * @param \\Illuminate\\Http\\Request $request\n     * @param \\Closure                 $next\n     *\n     * @return mixed\n     */\n    public function handle($request, Closure $next)\n    {\n        $route = $this->router->getCurrentRoute();\n\n        if (! $this->auth->check(false)) {\n            $this->auth->authenticate($route->getAuthenticationProviders());\n        }\n\n        return $next($request);\n    }\n}\n"
  },
  {
    "path": "src/Http/Middleware/PrepareController.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Http\\Middleware;\n\nuse Closure;\nuse Dingo\\Api\\Routing\\Router;\n\nclass PrepareController\n{\n    /**\n     * Dingo router instance.\n     *\n     * @var \\Dingo\\Api\\Routing\\Router\n     */\n    protected $router;\n\n    /**\n     * Create a new prepare controller instance.\n     *\n     * @param \\Dingo\\Api\\Routing\\Router $router\n     *\n     * @return void\n     */\n    public function __construct(Router $router)\n    {\n        $this->router = $router;\n    }\n\n    /**\n     * Handle the request.\n     *\n     * @param \\Dingo\\Api\\Http\\Request $request\n     * @param \\Closure                $next\n     *\n     * @return mixed\n     */\n    public function handle($request, Closure $next)\n    {\n        // To prepare the controller all we need to do is call the current method on the router to fetch\n        // the current route. This will create a new Dingo\\Api\\Routing\\Route instance and prepare the\n        // controller by binding it as a singleton in the container. This will result in the\n        // controller only be instantiated once per request.\n        $this->router->current();\n\n        return $next($request);\n    }\n}\n"
  },
  {
    "path": "src/Http/Middleware/RateLimit.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Http\\Middleware;\n\nuse Closure;\nuse Dingo\\Api\\Http\\Response;\nuse Dingo\\Api\\Routing\\Router;\nuse Dingo\\Api\\Http\\InternalRequest;\nuse Dingo\\Api\\Http\\RateLimit\\Handler;\nuse Dingo\\Api\\Exception\\RateLimitExceededException;\n\nclass RateLimit\n{\n    /**\n     * Router instance.\n     *\n     * @var \\Dingo\\Api\\Routing\\Router\n     */\n    protected $router;\n\n    /**\n     * Rate limit handler instance.\n     *\n     * @var \\Dingo\\Api\\Http\\RateLimit\\Handler\n     */\n    protected $handler;\n\n    /**\n     * Create a new rate limit middleware instance.\n     *\n     * @param \\Dingo\\Api\\Routing\\Router         $router\n     * @param \\Dingo\\Api\\Http\\RateLimit\\Handler $handler\n     *\n     * @return void\n     */\n    public function __construct(Router $router, Handler $handler)\n    {\n        $this->router = $router;\n        $this->handler = $handler;\n    }\n\n    /**\n     * Perform rate limiting before a request is executed.\n     *\n     * @param \\Dingo\\Api\\Http\\Request $request\n     * @param \\Closure                $next\n     *\n     * @throws \\Symfony\\Component\\HttpKernel\\Exception\\HttpException\n     *\n     * @return mixed\n     */\n    public function handle($request, Closure $next)\n    {\n        if ($request instanceof InternalRequest) {\n            return $next($request);\n        }\n\n        $route = $this->router->getCurrentRoute();\n\n        if ($route->hasThrottle()) {\n            $this->handler->setThrottle($route->getThrottle());\n        }\n\n        $this->handler->rateLimitRequest($request, $route->getRateLimit(), $route->getRateLimitExpiration());\n\n        if ($this->handler->exceededRateLimit()) {\n            throw new RateLimitExceededException('You have exceeded your rate limit.', null, $this->getHeaders());\n        }\n\n        $response = $next($request);\n\n        if ($this->handler->requestWasRateLimited()) {\n            return $this->responseWithHeaders($response);\n        }\n\n        return $response;\n    }\n\n    /**\n     * Send the response with the rate limit headers.\n     *\n     * @param \\Dingo\\Api\\Http\\Response $response\n     *\n     * @return \\Dingo\\Api\\Http\\Response\n     */\n    protected function responseWithHeaders($response)\n    {\n        foreach ($this->getHeaders() as $key => $value) {\n            $response->headers->set($key, $value);\n        }\n\n        return $response;\n    }\n\n    /**\n     * Get the headers for the response.\n     *\n     * @return array\n     */\n    protected function getHeaders()\n    {\n        return [\n            'X-RateLimit-Limit' => $this->handler->getThrottleLimit(),\n            'X-RateLimit-Remaining' => $this->handler->getRemainingLimit(),\n            'X-RateLimit-Reset' => $this->handler->getRateLimitReset(),\n        ];\n    }\n}\n"
  },
  {
    "path": "src/Http/Middleware/Request.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Http\\Middleware;\n\nuse Closure;\nuse Exception;\nuse Dingo\\Api\\Routing\\Router;\nuse Laravel\\Lumen\\Application;\nuse Illuminate\\Pipeline\\Pipeline;\nuse Dingo\\Api\\Http\\RequestValidator;\nuse Dingo\\Api\\Event\\RequestWasMatched;\nuse Dingo\\Api\\Http\\Request as HttpRequest;\nuse Illuminate\\Contracts\\Container\\Container;\nuse Dingo\\Api\\Contract\\Debug\\ExceptionHandler;\nuse Dingo\\Api\\Contract\\Http\\Request as RequestContract;\nuse Illuminate\\Contracts\\Events\\Dispatcher as EventDispatcher;\nuse Illuminate\\Contracts\\Debug\\ExceptionHandler as LaravelExceptionHandler;\n\nclass Request\n{\n    /**\n     * Application instance.\n     *\n     * @var \\Illuminate\\Contracts\\Foundation\\Application\n     */\n    protected $app;\n\n    /**\n     * Exception handler instance.\n     *\n     * @var \\Dingo\\Api\\Contract\\Debug\\ExceptionHandler\n     */\n    protected $exception;\n\n    /**\n     * Router instance.\n     *\n     * @var \\Dingo\\Api\\Routing\\Router\n     */\n    protected $router;\n\n    /**\n     * HTTP validator instance.\n     *\n     * @var \\Dingo\\Api\\Http\\Validator\n     */\n    protected $validator;\n\n    /**\n     * Event dispatcher instance.\n     *\n     * @var \\Illuminate\\Contracts\\Events\\Dispatcher\n     */\n    protected $events;\n\n    /**\n     * Array of middleware.\n     *\n     * @var array\n     */\n    protected $middleware = [];\n\n    /**\n     * Create a new request middleware instance.\n     *\n     * @param \\Illuminate\\Contracts\\Foundation\\Application $app\n     * @param \\Dingo\\Api\\Contract\\Debug\\ExceptionHandler   $exception\n     * @param \\Dingo\\Api\\Routing\\Router                    $router\n     * @param \\Dingo\\Api\\Http\\RequestValidator             $validator\n     * @param \\Illuminate\\Contracts\\Events\\Dispatcher      $events\n     *\n     * @return void\n     */\n    public function __construct(Container $app, ExceptionHandler $exception, Router $router, RequestValidator $validator, EventDispatcher $events)\n    {\n        $this->app = $app;\n        $this->exception = $exception;\n        $this->router = $router;\n        $this->validator = $validator;\n        $this->events = $events;\n    }\n\n    /**\n     * Handle an incoming request.\n     *\n     * @param \\Illuminate\\Http\\Request $request\n     * @param \\Closure                 $next\n     *\n     * @return mixed\n     */\n    public function handle($request, Closure $next)\n    {\n        try {\n            if ($this->validator->validateRequest($request)) {\n                $this->app->singleton(LaravelExceptionHandler::class, function ($app) {\n                    return $app[ExceptionHandler::class];\n                });\n\n                $request = $this->app->make(RequestContract::class)->createFromIlluminate($request);\n\n                $this->events->dispatch(new RequestWasMatched($request, $this->app));\n\n                return $this->sendRequestThroughRouter($request);\n            }\n        } catch (Exception $exception) {\n            $this->exception->report($exception);\n\n            return $this->exception->handle($exception);\n        }\n\n        return $next($request);\n    }\n\n    /**\n     * Send the request through the Dingo router.\n     *\n     * @param \\Dingo\\Api\\Http\\Request $request\n     *\n     * @return \\Dingo\\Api\\Http\\Response\n     */\n    protected function sendRequestThroughRouter(HttpRequest $request)\n    {\n        $this->app->instance('request', $request);\n\n        return (new Pipeline($this->app))->send($request)->through($this->middleware)->then(function ($request) {\n            return $this->router->dispatch($request);\n        });\n    }\n\n    /**\n     * Call the terminate method on middlewares.\n     *\n     * @return void\n     */\n    public function terminate($request, $response)\n    {\n        if (! ($request = $this->app['request']) instanceof HttpRequest) {\n            return;\n        }\n\n        // Laravel's route middlewares can be terminated just like application\n        // middleware, so we'll gather all the route middleware here.\n        // On Lumen this will simply be an empty array as it does\n        // not implement terminable route middleware.\n        $middlewares = $this->gatherRouteMiddlewares($request);\n\n        // Because of how middleware is executed on Lumen we'll need to merge in the\n        // application middlewares now so that we can terminate them. Laravel does\n        // not need this as it handles things a little more gracefully so it\n        // can terminate the application ones itself.\n        if (class_exists(Application::class, false)) {\n            $middlewares = array_merge($middlewares, $this->middleware);\n        }\n\n        foreach ($middlewares as $middleware) {\n            if ($middleware instanceof Closure) {\n                continue;\n            }\n\n            [$name, $parameters] = $this->parseMiddleware($middleware);\n\n            $instance = $this->app->make($name);\n\n            if (method_exists($instance, 'terminate')) {\n                $instance->terminate($request, $response);\n            }\n        }\n    }\n\n    /**\n     * Parse a middleware string to get the name and parameters.\n     *\n     * @author Taylor Otwell\n     *\n     * @param string $middleware\n     *\n     * @return array\n     */\n    protected function parseMiddleware($middleware)\n    {\n        [$name, $parameters] = array_pad(explode(':', $middleware, 2), 2, []);\n\n        if (is_string($parameters)) {\n            $parameters = explode(',', $parameters);\n        }\n\n        return [$name, $parameters];\n    }\n\n    /**\n     * Gather the middlewares for the route.\n     *\n     * @param \\Dingo\\Api\\Http\\Request $request\n     *\n     * @return array\n     */\n    protected function gatherRouteMiddlewares($request)\n    {\n        if ($route = $request->route()) {\n            return $this->router->gatherRouteMiddlewares($route);\n        }\n\n        return [];\n    }\n\n    /**\n     * Set the middlewares.\n     *\n     * @param array $middleware\n     *\n     * @return void\n     */\n    public function setMiddlewares(array $middleware)\n    {\n        $this->middleware = $middleware;\n    }\n\n    /**\n     * Merge new middlewares onto the existing middlewares.\n     *\n     * @param array $middleware\n     *\n     * @return void\n     */\n    public function mergeMiddlewares(array $middleware)\n    {\n        $this->middleware = array_merge($this->middleware, $middleware);\n    }\n}\n"
  },
  {
    "path": "src/Http/Parser/Accept.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Http\\Parser;\n\nuse Illuminate\\Http\\Request;\nuse Dingo\\Api\\Contract\\Http\\Parser;\nuse Symfony\\Component\\HttpKernel\\Exception\\BadRequestHttpException;\n\nclass Accept implements Parser\n{\n    /**\n     * Standards tree.\n     *\n     * @var string\n     */\n    protected $standardsTree;\n\n    /**\n     * API subtype.\n     *\n     * @var string\n     */\n    protected $subtype;\n\n    /**\n     * Default version.\n     *\n     * @var string\n     */\n    protected $version;\n\n    /**\n     * Default format.\n     *\n     * @var string\n     */\n    protected $format;\n\n    /**\n     * Create a new accept parser instance.\n     *\n     * @param string $standardsTree\n     * @param string $subtype\n     * @param string $version\n     * @param string $format\n     *\n     * @return void\n     */\n    public function __construct($standardsTree, $subtype, $version, $format)\n    {\n        $this->standardsTree = $standardsTree;\n        $this->subtype = $subtype;\n        $this->version = $version;\n        $this->format = $format;\n    }\n\n    /**\n     * Parse the accept header on the incoming request. If strict is enabled\n     * then the accept header must be available and must be a valid match.\n     *\n     * @param \\Illuminate\\Http\\Request $request\n     * @param bool                     $strict\n     *\n     * @throws \\Symfony\\Component\\HttpKernel\\Exception\\BadRequestHttpException\n     *\n     * @return array\n     */\n    public function parse(Request $request, $strict = false)\n    {\n        $pattern = '/application\\/'.$this->standardsTree.'\\.('.$this->subtype.')\\.([\\w\\d\\.\\-]+)\\+([\\w]+)/';\n\n        if (! preg_match($pattern, $request->header('accept'), $matches)) {\n            if ($strict) {\n                throw new BadRequestHttpException('Accept header could not be properly parsed because of a strict matching process.');\n            }\n\n            $default = 'application/'.$this->standardsTree.'.'.$this->subtype.'.'.$this->version.'+'.$this->format;\n\n            preg_match($pattern, $default, $matches);\n        }\n\n        return array_combine(['subtype', 'version', 'format'], array_slice($matches, 1));\n    }\n}\n"
  },
  {
    "path": "src/Http/RateLimit/Handler.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Http\\RateLimit;\n\nuse Dingo\\Api\\Http\\Request;\nuse Illuminate\\Support\\Carbon;\nuse Illuminate\\Cache\\CacheManager;\nuse Illuminate\\Support\\Collection;\nuse Illuminate\\Container\\Container;\nuse Dingo\\Api\\Http\\RateLimit\\Throttle\\Route;\nuse Dingo\\Api\\Contract\\Http\\RateLimit\\Throttle;\nuse Dingo\\Api\\Contract\\Http\\RateLimit\\HasRateLimiter;\n\nclass Handler\n{\n    /**\n     * Container instance.\n     *\n     * @var \\Illuminate\\Container\\Container\n     */\n    protected $container;\n\n    /**\n     * Cache instance.\n     *\n     * @var \\Illuminate\\Cache\\CacheManager\n     */\n    protected $cache;\n\n    /**\n     * Registered throttles.\n     *\n     * @var \\Illuminate\\Support\\Collection\n     */\n    protected $throttles;\n\n    /**\n     * Throttle used for rate limiting.\n     *\n     * @var \\Dingo\\Api\\Contract\\Http\\RateLimit\\Throttle\n     */\n    protected $throttle;\n\n    /**\n     * Request instance being throttled.\n     *\n     * @var \\Dingo\\Api\\Http\\Request\n     */\n    protected $request;\n\n    /**\n     * The key prefix used when throttling route specific requests.\n     *\n     * @var string\n     */\n    protected $keyPrefix;\n\n    /**\n     * A callback used to define the limiter.\n     *\n     * @var callable\n     */\n    protected $limiter;\n\n    /**\n     * Create a new rate limit handler instance.\n     *\n     * @param \\Illuminate\\Container\\Container $container\n     * @param \\Illuminate\\Cache\\CacheManager  $cache\n     * @param array                           $throttles\n     *\n     * @return void\n     */\n    public function __construct(Container $container, CacheManager $cache, array $throttles)\n    {\n        $this->cache = $cache;\n        $this->container = $container;\n        $this->throttles = new Collection($throttles);\n    }\n\n    /**\n     * Execute the rate limiting for the given request.\n     *\n     * @param \\Dingo\\Api\\Http\\Request $request\n     * @param int                     $limit\n     * @param int                     $expires\n     *\n     * @return void\n     */\n    public function rateLimitRequest(Request $request, $limit = 0, $expires = 0)\n    {\n        $this->request = $request;\n\n        // If the throttle instance is already set then we'll just carry on as\n        // per usual.\n        if ($this->throttle instanceof Throttle) {\n\n            // If the developer specified a certain amount of requests or expiration\n        // time on a specific route then we'll always use the route specific\n        // throttle with the given values.\n        } elseif ($limit > 0 || $expires > 0) {\n            $this->throttle = new Route(['limit' => $limit, 'expires' => $expires]);\n            $this->keyPrefix = sha1($request->path());\n\n        // Otherwise we'll use the throttle that gives the consumer the largest\n        // amount of requests. If no matching throttle is found then rate\n        // limiting will not be imposed for the request.\n        } else {\n            $this->throttle = $this->getMatchingThrottles()->sort(function ($a, $b) {\n                return $a->getLimit() < $b->getLimit();\n            })->first();\n        }\n\n        if (is_null($this->throttle)) {\n            return;\n        }\n\n        if ($this->throttle instanceof HasRateLimiter) {\n            $this->setRateLimiter([$this->throttle, 'getRateLimiter']);\n        }\n\n        $this->prepareCacheStore();\n\n        $this->cache('requests', 0, $this->throttle->getExpires());\n        $this->cache('expires', $this->throttle->getExpires(), $this->throttle->getExpires());\n        $this->cache('reset', time() + ($this->throttle->getExpires() * 60), $this->throttle->getExpires());\n        $this->increment('requests');\n    }\n\n    /**\n     * Prepare the cache store.\n     *\n     * @return void\n     */\n    protected function prepareCacheStore()\n    {\n        if ($this->retrieve('expires') != $this->throttle->getExpires()) {\n            $this->forget('requests');\n            $this->forget('expires');\n            $this->forget('reset');\n        }\n    }\n\n    /**\n     * Determine if the rate limit has been exceeded.\n     *\n     * @return bool\n     */\n    public function exceededRateLimit()\n    {\n        return $this->requestWasRateLimited() ? $this->retrieve('requests') > $this->throttle->getLimit() : false;\n    }\n\n    /**\n     * Get matching throttles after executing the condition of each throttle.\n     *\n     * @return \\Illuminate\\Support\\Collection\n     */\n    protected function getMatchingThrottles()\n    {\n        return $this->throttles->filter(function ($throttle) {\n            return $throttle->match($this->container);\n        });\n    }\n\n    /**\n     * Namespace a cache key.\n     *\n     * @param string $key\n     *\n     * @return string\n     */\n    protected function key($key)\n    {\n        return sprintf('dingo.api.%s.%s', $key, $this->getRateLimiter());\n    }\n\n    /**\n     * Cache a value under a given key for a certain amount of minutes.\n     *\n     * @param string $key\n     * @param mixed  $value\n     * @param int    $minutes\n     *\n     * @return void\n     */\n    protected function cache($key, $value, $minutes)\n    {\n        $this->cache->add($this->key($key), $value, Carbon::now()->addMinutes($minutes));\n    }\n\n    /**\n     * Retrieve a value from the cache store.\n     *\n     * @param string $key\n     *\n     * @return mixed\n     */\n    protected function retrieve($key)\n    {\n        return $this->cache->get($this->key($key));\n    }\n\n    /**\n     * Increment a key in the cache.\n     *\n     * @param string $key\n     *\n     * @return void\n     */\n    protected function increment($key)\n    {\n        $this->cache->increment($this->key($key));\n    }\n\n    /**\n     * Forget a key in the cache.\n     *\n     * @param string $key\n     *\n     * @return void\n     */\n    protected function forget($key)\n    {\n        $this->cache->forget($this->key($key));\n    }\n\n    /**\n     * Determine if the request was rate limited.\n     *\n     * @return bool\n     */\n    public function requestWasRateLimited()\n    {\n        return ! is_null($this->throttle);\n    }\n\n    /**\n     * Get the rate limiter.\n     *\n     * @return string\n     */\n    public function getRateLimiter()\n    {\n        return call_user_func($this->limiter ?: function ($container, $request) {\n            return $request->getClientIp();\n        }, $this->container, $this->request);\n    }\n\n    /**\n     * Set the rate limiter.\n     *\n     * @param callable $limiter\n     *\n     * @return void\n     */\n    public function setRateLimiter(callable $limiter)\n    {\n        $this->limiter = $limiter;\n    }\n\n    /**\n     * Set the throttle to use for rate limiting.\n     *\n     * @param string|\\Dingo\\Api\\Contract\\Http\\RateLimit\\Throttle $throttle\n     *\n     * @return void\n     */\n    public function setThrottle($throttle)\n    {\n        if (is_string($throttle)) {\n            $throttle = $this->container->make($throttle);\n        }\n\n        $this->throttle = $throttle;\n    }\n\n    /**\n     * Get the throttle used to rate limit the request.\n     *\n     * @return \\Dingo\\Api\\Contract\\Http\\RateLimit\\Throttle\n     */\n    public function getThrottle()\n    {\n        return $this->throttle;\n    }\n\n    /**\n     * Get the limit of the throttle used.\n     *\n     * @return int\n     */\n    public function getThrottleLimit()\n    {\n        return $this->throttle->getLimit();\n    }\n\n    /**\n     * Get the remaining limit before the consumer is rate limited.\n     *\n     * @return int\n     */\n    public function getRemainingLimit()\n    {\n        $remaining = $this->throttle->getLimit() - $this->retrieve('requests');\n\n        return $remaining > 0 ? $remaining : 0;\n    }\n\n    /**\n     * Get the timestamp for when the current rate limiting will expire.\n     *\n     * @return int\n     */\n    public function getRateLimitReset()\n    {\n        return $this->retrieve('reset');\n    }\n\n    /**\n     * Extend the rate limiter by adding a new throttle.\n     *\n     * @param callable|\\Dingo\\Api\\Http\\RateLimit\\Throttle $throttle\n     *\n     * @return void\n     */\n    public function extend($throttle)\n    {\n        if (is_callable($throttle)) {\n            $throttle = call_user_func($throttle, $this->container);\n        }\n\n        $this->throttles->push($throttle);\n    }\n}\n"
  },
  {
    "path": "src/Http/RateLimit/Throttle/Authenticated.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Http\\RateLimit\\Throttle;\n\nuse Illuminate\\Container\\Container;\n\nclass Authenticated extends Throttle\n{\n    /**\n     * Authenticated throttle will be matched when request is authenticated.\n     *\n     * @param \\Illuminate\\Container\\Container $container\n     *\n     * @return bool\n     */\n    public function match(Container $container)\n    {\n        return $container['api.auth']->check();\n    }\n}\n"
  },
  {
    "path": "src/Http/RateLimit/Throttle/Route.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Http\\RateLimit\\Throttle;\n\nuse Illuminate\\Container\\Container;\n\nclass Route extends Throttle\n{\n    /**\n     * Route specific throttles always match.\n     *\n     * @param \\Illuminate\\Container\\Container $container\n     *\n     * @return bool\n     */\n    public function match(Container $container)\n    {\n        return true;\n    }\n}\n"
  },
  {
    "path": "src/Http/RateLimit/Throttle/Throttle.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Http\\RateLimit\\Throttle;\n\nuse Dingo\\Api\\Contract\\Http\\RateLimit\\Throttle as RateLimitThrottle;\n\nabstract class Throttle implements RateLimitThrottle\n{\n    /**\n     * Array of throttle options.\n     *\n     * @var array\n     */\n    protected $options = ['limit' => 60, 'expires' => 60];\n\n    /**\n     * Create a new throttle instance.\n     *\n     * @param array $options\n     *\n     * @return void\n     */\n    public function __construct(array $options = [])\n    {\n        $this->options = array_merge($this->options, $options);\n    }\n\n    /**\n     * Get the throttles request limit.\n     *\n     * @return int\n     */\n    public function getLimit()\n    {\n        return $this->options['limit'];\n    }\n\n    /**\n     * Get the time in minutes that the throttles request limit will expire.\n     *\n     * @return int\n     */\n    public function getExpires()\n    {\n        return $this->options['expires'];\n    }\n}\n"
  },
  {
    "path": "src/Http/RateLimit/Throttle/Unauthenticated.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Http\\RateLimit\\Throttle;\n\nuse Illuminate\\Container\\Container;\n\nclass Unauthenticated extends Throttle\n{\n    /**\n     * Unauthenticated throttle will be matched when request is not authenticated.\n     *\n     * @param \\Illuminate\\Container\\Container $container\n     *\n     * @return bool\n     */\n    public function match(Container $container)\n    {\n        return ! $container['api.auth']->check();\n    }\n}\n"
  },
  {
    "path": "src/Http/Request.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Http;\n\nuse Dingo\\Api\\Http\\Parser\\Accept;\nuse Illuminate\\Http\\Request as IlluminateRequest;\nuse Dingo\\Api\\Contract\\Http\\Request as RequestInterface;\n\nclass Request extends IlluminateRequest implements RequestInterface\n{\n    /**\n     * Accept parser instance.\n     *\n     * @var \\Dingo\\Api\\Http\\Parser\\Accept\n     */\n    protected static $acceptParser;\n\n    /**\n     * Parsed accept header for the request.\n     *\n     * @var array\n     */\n    protected $accept;\n\n    /**\n     * Create a new Dingo request instance from an Illuminate request instance.\n     *\n     * @param \\Illuminate\\Http\\Request $old\n     *\n     * @return \\Dingo\\Api\\Http\\Request\n     */\n    public function createFromIlluminate(IlluminateRequest $old)\n    {\n        $new = new static(\n            $old->query->all(), $old->request->all(), $old->attributes->all(),\n            $old->cookies->all(), $old->files->all(), $old->server->all(), $old->content\n        );\n\n        if ($session = $old->getSession()) {\n            $new->setLaravelSession($old->getSession());\n        }\n\n        $new->setRouteResolver($old->getRouteResolver());\n        $new->setUserResolver($old->getUserResolver());\n\n        return $new;\n    }\n\n    /**\n     * Get the defined version.\n     *\n     * @return string\n     */\n    public function version()\n    {\n        $this->parseAcceptHeader();\n\n        return $this->accept['version'];\n    }\n\n    /**\n     * Get the defined subtype.\n     *\n     * @return string\n     */\n    public function subtype()\n    {\n        $this->parseAcceptHeader();\n\n        return $this->accept['subtype'];\n    }\n\n    /**\n     * Get the expected format type.\n     *\n     * @return string\n     */\n    public function format($default = 'html')\n    {\n        $this->parseAcceptHeader();\n\n        return $this->accept['format'] ?: parent::format($default);\n    }\n\n    /**\n     * Parse the accept header.\n     *\n     * @return void\n     */\n    protected function parseAcceptHeader()\n    {\n        if ($this->accept) {\n            return;\n        }\n\n        $this->accept = static::$acceptParser->parse($this);\n    }\n\n    /**\n     * Set the accept parser instance.\n     *\n     * @param \\Dingo\\Api\\Http\\Parser\\Accept $acceptParser\n     *\n     * @return void\n     */\n    public static function setAcceptParser(Accept $acceptParser)\n    {\n        static::$acceptParser = $acceptParser;\n    }\n\n    /**\n     * Get the accept parser instance.\n     *\n     * @return \\Dingo\\Api\\Http\\Parser\\Accept\n     */\n    public static function getAcceptParser()\n    {\n        return static::$acceptParser;\n    }\n}\n"
  },
  {
    "path": "src/Http/RequestValidator.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Http;\n\nuse Illuminate\\Container\\Container;\nuse Dingo\\Api\\Http\\Validation\\Accept;\nuse Dingo\\Api\\Http\\Validation\\Domain;\nuse Dingo\\Api\\Http\\Validation\\Prefix;\nuse Dingo\\Api\\Contract\\Http\\Validator;\nuse Illuminate\\Http\\Request as IlluminateRequest;\n\nclass RequestValidator\n{\n    /**\n     * Container instance.\n     *\n     * @var \\Illuminate\\Container\\Container\n     */\n    protected $container;\n\n    /**\n     * Array of request validators.\n     *\n     * @var array\n     */\n    protected $validators = [\n        Domain::class,\n        Prefix::class,\n    ];\n\n    /**\n     * Create a new request validator instance.\n     *\n     * @param \\Illuminate\\Container\\Container $container\n     *\n     * @return void\n     */\n    public function __construct(Container $container)\n    {\n        $this->container = $container;\n    }\n\n    /**\n     * Replace the validators.\n     *\n     * @param array $validators\n     *\n     * @return void\n     */\n    public function replace(array $validators)\n    {\n        $this->validators = $validators;\n    }\n\n    /**\n     * Merge an array of validators.\n     *\n     * @param array $validators\n     *\n     * @return void\n     */\n    public function merge(array $validators)\n    {\n        $this->validators = array_merge($this->validators, $validators);\n    }\n\n    /**\n     * Extend the validators.\n     *\n     * @param string|\\Dingo\\Api\\Http\\Validator $validator\n     *\n     * @return void\n     */\n    public function extend($validator)\n    {\n        $this->validators[] = $validator;\n    }\n\n    /**\n     * Validate a request.\n     *\n     * @param \\Illuminate\\Http\\Request $request\n     *\n     * @return bool\n     */\n    public function validateRequest(IlluminateRequest $request)\n    {\n        $passed = false;\n\n        foreach ($this->validators as $validator) {\n            $validator = $this->container->make($validator);\n\n            if ($validator instanceof Validator && $validator->validate($request)) {\n                $passed = true;\n            }\n        }\n\n        // The accept validator will always be run once any of the previous validators have\n        // been run. This ensures that we only run the accept validator once we know we\n        // have a request that is targeting the API.\n        if ($passed) {\n            $this->container->make(Accept::class)->validate($request);\n        }\n\n        return $passed;\n    }\n}\n"
  },
  {
    "path": "src/Http/Response/Factory.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Http\\Response;\n\nuse Closure;\nuse ErrorException;\nuse Illuminate\\Support\\Str;\nuse Dingo\\Api\\Http\\Response;\nuse Illuminate\\Support\\Collection;\nuse Illuminate\\Contracts\\Pagination\\Paginator;\nuse Dingo\\Api\\Transformer\\Factory as TransformerFactory;\nuse Symfony\\Component\\HttpKernel\\Exception\\HttpException;\n\nclass Factory\n{\n    /**\n     * Transformer factory instance.\n     *\n     * @var \\Dingo\\Api\\Transformer\\Factory\n     */\n    protected $transformer;\n\n    /**\n     * Create a new response factory instance.\n     *\n     * @param \\Dingo\\Api\\Transformer\\Factory $transformer\n     *\n     * @return void\n     */\n    public function __construct(TransformerFactory $transformer)\n    {\n        $this->transformer = $transformer;\n    }\n\n    /**\n     * Respond with a created response and associate a location if provided.\n     *\n     * @param null|string $location\n     *\n     * @return \\Dingo\\Api\\Http\\Response\n     */\n    public function created($location = null, $content = null)\n    {\n        $response = new Response($content);\n        $response->setStatusCode(201);\n\n        if (! is_null($location)) {\n            $response->header('Location', $location);\n        }\n\n        return $response;\n    }\n\n    /**\n     * Respond with an accepted response and associate a location and/or content if provided.\n     *\n     * @param null|string $location\n     * @param mixed       $content\n     *\n     * @return \\Dingo\\Api\\Http\\Response\n     */\n    public function accepted($location = null, $content = null)\n    {\n        $response = new Response($content);\n        $response->setStatusCode(202);\n\n        if (! is_null($location)) {\n            $response->header('Location', $location);\n        }\n\n        return $response;\n    }\n\n    /**\n     * Respond with a no content response.\n     *\n     * @return \\Dingo\\Api\\Http\\Response\n     */\n    public function noContent()\n    {\n        $response = new Response(null);\n\n        return $response->setStatusCode(204);\n    }\n\n    /**\n     * Bind a collection to a transformer and start building a response.\n     *\n     * @param \\Illuminate\\Support\\Collection $collection\n     * @param string|callable|object         $transformer\n     * @param array|\\Closure                 $parameters\n     * @param \\Closure|null                  $after\n     *\n     * @return \\Dingo\\Api\\Http\\Response\n     */\n    public function collection(Collection $collection, $transformer = null, $parameters = [], Closure $after = null)\n    {\n        if ($collection->isEmpty()) {\n            $class = get_class($collection);\n        } else {\n            $class = get_class($collection->first());\n        }\n\n        if ($parameters instanceof \\Closure) {\n            $after = $parameters;\n            $parameters = [];\n        }\n\n        if ($transformer !== null) {\n            $binding = $this->transformer->register($class, $transformer, $parameters, $after);\n        } else {\n            $binding = $this->transformer->getBinding($collection);\n        }\n\n        return new Response($collection, 200, [], $binding);\n    }\n\n    /**\n     * Bind an item to a transformer and start building a response.\n     *\n     * @param object                         $item\n     * @param null|string|callable|object    $transformer\n     * @param array                          $parameters\n     * @param \\Closure                       $after\n     *\n     * @return \\Dingo\\Api\\Http\\Response\n     */\n    public function item($item, $transformer = null, $parameters = [], Closure $after = null)\n    {\n        // Check for $item being null\n        if (! is_null($item)) {\n            $class = get_class($item);\n        } else {\n            $class = \\StdClass::class;\n        }\n\n        if ($parameters instanceof \\Closure) {\n            $after = $parameters;\n            $parameters = [];\n        }\n\n        if ($transformer !== null) {\n            $binding = $this->transformer->register($class, $transformer, $parameters, $after);\n        } else {\n            $binding = $this->transformer->getBinding($item);\n        }\n\n        return new Response($item, 200, [], $binding);\n    }\n\n    /**\n     * Bind an arbitrary array to a transformer and start building a response.\n     *\n     * @param array $array\n     * @param $transformer\n     * @param array $parameters\n     * @param Closure|null $after\n     *\n     * @return Response\n     */\n    public function array(array $array, $transformer = null, $parameters = [], Closure $after = null)\n    {\n        if ($parameters instanceof \\Closure) {\n            $after = $parameters;\n            $parameters = [];\n        }\n\n        // For backwards compatibility, allow no transformer\n        if ($transformer) {\n            // Use the PHP stdClass for this purpose, as a work-around, since we need to register a class binding\n            $class = 'stdClass';\n            // This will convert the array into an stdClass\n            $array = (object) $array;\n\n            $binding = $this->transformer->register($class, $transformer, $parameters, $after);\n        } else {\n            $binding = null;\n        }\n\n        return new Response($array, 200, [], $binding);\n    }\n\n    /**\n     * Bind a paginator to a transformer and start building a response.\n     *\n     * @param \\Illuminate\\Contracts\\Pagination\\Paginator $paginator\n     * @param null|string|callable|object                $transformer\n     * @param array                                      $parameters\n     * @param \\Closure                                   $after\n     *\n     * @return \\Dingo\\Api\\Http\\Response\n     */\n    public function paginator(Paginator $paginator, $transformer = null, array $parameters = [], Closure $after = null)\n    {\n        if ($paginator->isEmpty()) {\n            $class = get_class($paginator);\n        } else {\n            $class = get_class($paginator->first());\n        }\n\n        if ($transformer !== null) {\n            $binding = $this->transformer->register($class, $transformer, $parameters, $after);\n        } else {\n            $binding = $this->transformer->getBinding($paginator->first());\n        }\n\n        return new Response($paginator, 200, [], $binding);\n    }\n\n    /**\n     * Return an error response.\n     *\n     * @param string $message\n     * @param int    $statusCode\n     *\n     * @throws \\Symfony\\Component\\HttpKernel\\Exception\\HttpException\n     *\n     * @return void\n     */\n    public function error($message, $statusCode)\n    {\n        throw new HttpException($statusCode, $message);\n    }\n\n    /**\n     * Return a 404 not found error.\n     *\n     * @param string $message\n     *\n     * @throws \\Symfony\\Component\\HttpKernel\\Exception\\HttpException\n     *\n     * @return void\n     */\n    public function errorNotFound($message = 'Not Found')\n    {\n        $this->error($message, 404);\n    }\n\n    /**\n     * Return a 400 bad request error.\n     *\n     * @param string $message\n     *\n     * @throws \\Symfony\\Component\\HttpKernel\\Exception\\HttpException\n     *\n     * @return void\n     */\n    public function errorBadRequest($message = 'Bad Request')\n    {\n        $this->error($message, 400);\n    }\n\n    /**\n     * Return a 403 forbidden error.\n     *\n     * @param string $message\n     *\n     * @throws \\Symfony\\Component\\HttpKernel\\Exception\\HttpException\n     *\n     * @return void\n     */\n    public function errorForbidden($message = 'Forbidden')\n    {\n        $this->error($message, 403);\n    }\n\n    /**\n     * Return a 500 internal server error.\n     *\n     * @param string $message\n     *\n     * @throws \\Symfony\\Component\\HttpKernel\\Exception\\HttpException\n     *\n     * @return void\n     */\n    public function errorInternal($message = 'Internal Error')\n    {\n        $this->error($message, 500);\n    }\n\n    /**\n     * Return a 401 unauthorized error.\n     *\n     * @param string $message\n     *\n     * @throws \\Symfony\\Component\\HttpKernel\\Exception\\HttpException\n     *\n     * @return void\n     */\n    public function errorUnauthorized($message = 'Unauthorized')\n    {\n        $this->error($message, 401);\n    }\n\n    /**\n     * Return a 405 method not allowed error.\n     *\n     * @param string $message\n     *\n     * @throws \\Symfony\\Component\\HttpKernel\\Exception\\HttpException\n     *\n     * @return void\n     */\n    public function errorMethodNotAllowed($message = 'Method Not Allowed')\n    {\n        $this->error($message, 405);\n    }\n\n    /**\n     * Call magic methods beginning with \"with\".\n     *\n     * @param string $method\n     * @param array  $parameters\n     *\n     * @throws \\ErrorException\n     *\n     * @return mixed\n     */\n    public function __call($method, $parameters)\n    {\n        if (Str::startsWith($method, 'with')) {\n            return call_user_func_array([$this, Str::camel(substr($method, 4))], $parameters);\n\n        // Because PHP won't let us name the method \"array\" we'll simply watch for it\n            // in here and return the new binding. Gross. This is now DEPRECATED and\n            // should not be used. Just return an array or a new response instance.\n        } elseif ($method == 'array') {\n            return new Response($parameters[0]);\n        }\n\n        throw new ErrorException('Undefined method '.get_class($this).'::'.$method);\n    }\n}\n"
  },
  {
    "path": "src/Http/Response/Format/Format.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Http\\Response\\Format;\n\nabstract class Format\n{\n    /**\n     * Illuminate request instance.\n     *\n     * @var \\Illuminate\\Http\\Request\n     */\n    protected $request;\n\n    /**\n     * Illuminate response instance.\n     *\n     * @var \\Illuminate\\Http\\Response\n     */\n    protected $response;\n\n    /*\n     * Array of formats' options.\n     *\n     * @var array\n     */\n    protected $options;\n\n    /**\n     * Set the request instance.\n     *\n     * @param \\Illuminate\\Http\\Request $request\n     *\n     * @return \\Dingo\\Api\\Http\\Response\\Format\\Format\n     */\n    public function setRequest($request)\n    {\n        $this->request = $request;\n\n        return $this;\n    }\n\n    /**\n     * Set the response instance.\n     *\n     * @param \\Illuminate\\Http\\Response $response\n     *\n     * @return \\Dingo\\Api\\Http\\Response\\Format\\Format\n     */\n    public function setResponse($response)\n    {\n        $this->response = $response;\n\n        return $this;\n    }\n\n    /**\n     * Set the formats' options.\n     *\n     * @param array $options\n     *\n     * @return \\Dingo\\Api\\Http\\Response\\Format\\Format\n     */\n    public function setOptions(array $options)\n    {\n        $this->options = $options;\n\n        return $this;\n    }\n\n    /**\n     * Format an Eloquent model.\n     *\n     * @param \\Illuminate\\Database\\Eloquent\\Model $model\n     *\n     * @return string\n     */\n    abstract public function formatEloquentModel($model);\n\n    /**\n     * Format an Eloquent collection.\n     *\n     * @param \\Illuminate\\Database\\Eloquent\\Collection $collection\n     *\n     * @return string\n     */\n    abstract public function formatEloquentCollection($collection);\n\n    /**\n     * Format an array or instance implementing Arrayable.\n     *\n     * @param array|\\Illuminate\\Contracts\\Support\\Arrayable $content\n     *\n     * @return string\n     */\n    abstract public function formatArray($content);\n\n    /**\n     * Get the response content type.\n     *\n     * @return string\n     */\n    abstract public function getContentType();\n}\n"
  },
  {
    "path": "src/Http/Response/Format/Json.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Http\\Response\\Format;\n\nuse Illuminate\\Support\\Str;\nuse Illuminate\\Contracts\\Support\\Arrayable;\n\nclass Json extends Format\n{\n    /*\n     * JSON format (as well as JSONP) uses JsonOptionalFormatting trait, which\n     * provides extra functionality for the process of encoding data to\n     * its JSON representation.\n     */\n    use JsonOptionalFormatting;\n\n    /**\n     * Format an Eloquent model.\n     *\n     * @param \\Illuminate\\Database\\Eloquent\\Model $model\n     *\n     * @return string\n     */\n    public function formatEloquentModel($model)\n    {\n        $key = Str::singular($model->getTable());\n\n        if (! $model::$snakeAttributes) {\n            $key = Str::camel($key);\n        }\n\n        return $this->encode([$key => $model->toArray()]);\n    }\n\n    /**\n     * Format an Eloquent collection.\n     *\n     * @param \\Illuminate\\Database\\Eloquent\\Collection $collection\n     *\n     * @return string\n     */\n    public function formatEloquentCollection($collection)\n    {\n        if ($collection->isEmpty()) {\n            return $this->encode([]);\n        }\n\n        $model = $collection->first();\n        $key = Str::plural($model->getTable());\n\n        if (! $model::$snakeAttributes) {\n            $key = Str::camel($key);\n        }\n\n        return $this->encode([$key => $collection->toArray()]);\n    }\n\n    /**\n     * Format an array or instance implementing Arrayable.\n     *\n     * @param array|\\Illuminate\\Contracts\\Support\\Arrayable $content\n     *\n     * @return string\n     */\n    public function formatArray($content)\n    {\n        $content = $this->morphToArray($content);\n\n        array_walk_recursive($content, function (&$value) {\n            $value = $this->morphToArray($value);\n        });\n\n        return $this->encode($content);\n    }\n\n    /**\n     * Get the response content type.\n     *\n     * @return string\n     */\n    public function getContentType()\n    {\n        return 'application/json';\n    }\n\n    /**\n     * Morph a value to an array.\n     *\n     * @param array|\\Illuminate\\Contracts\\Support\\Arrayable $value\n     *\n     * @return array\n     */\n    protected function morphToArray($value)\n    {\n        return $value instanceof Arrayable ? $value->toArray() : $value;\n    }\n\n    /**\n     * Encode the content to its JSON representation.\n     *\n     * @param mixed $content\n     *\n     * @return string\n     */\n    protected function encode($content)\n    {\n        $jsonEncodeOptions = [];\n\n        // Here is a place, where any available JSON encoding options, that\n        // deal with users' requirements to JSON response formatting and\n        // structure, can be conveniently applied to tweak the output.\n\n        if ($this->isJsonPrettyPrintEnabled()) {\n            $jsonEncodeOptions[] = JSON_PRETTY_PRINT;\n            $jsonEncodeOptions[] = JSON_UNESCAPED_UNICODE;\n        }\n\n        $encodedString = $this->performJsonEncoding($content, $jsonEncodeOptions);\n\n        if ($this->isCustomIndentStyleRequired()) {\n            $encodedString = $this->indentPrettyPrintedJson(\n                $encodedString,\n                $this->options['indent_style']\n            );\n        }\n\n        return $encodedString;\n    }\n}\n"
  },
  {
    "path": "src/Http/Response/Format/JsonOptionalFormatting.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Http\\Response\\Format;\n\ntrait JsonOptionalFormatting\n{\n    /*\n     * Supported JSON pretty print indent styles.\n     *\n     * @var array\n     */\n    protected $indentStyles = [\n        'tab',\n        'space',\n    ];\n\n    /*\n     * Indent styles, that are allowed to have various indent size.\n     *\n     * @var array\n     */\n    protected $hasVariousIndentSize = [\n        'space',\n    ];\n\n    /*\n     * Indent chars, associated with indent styles.\n     *\n     * @var array\n     */\n    protected $indentChars = [\n        'tab' => \"\\t\",\n        'space' => ' ',\n    ];\n\n    /*\n     * JSON constants, that are allowed to be used as options while encoding.\n     * Whitelist can be extended by other options in the future.\n     *\n     * @see http://php.net/manual/ru/json.constants.php\n     *\n     * @var array\n     */\n    protected $jsonEncodeOptionsWhitelist = [\n        JSON_PRETTY_PRINT,\n        JSON_UNESCAPED_UNICODE,\n    ];\n\n    /**\n     * Determine if JSON pretty print option is set to true.\n     *\n     * @return bool\n     */\n    protected function isJsonPrettyPrintEnabled()\n    {\n        return isset($this->options['pretty_print']) && $this->options['pretty_print'] === true;\n    }\n\n    /**\n     * Determine if JSON custom indent style is set.\n     *\n     * @return bool\n     */\n    protected function isCustomIndentStyleRequired()\n    {\n        return $this->isJsonPrettyPrintEnabled() &&\n            isset($this->options['indent_style']) &&\n            in_array($this->options['indent_style'], $this->indentStyles);\n    }\n\n    /**\n     * Perform JSON encode.\n     *\n     * @param string $content\n     * @param array  $jsonEncodeOptions\n     *\n     * @return string\n     */\n    protected function performJsonEncoding($content, array $jsonEncodeOptions = [])\n    {\n        $jsonEncodeOptions = $this->filterJsonEncodeOptions($jsonEncodeOptions);\n\n        $optionsBitmask = $this->calucateJsonEncodeOptionsBitmask($jsonEncodeOptions);\n\n        if (($encodedString = json_encode($content, $optionsBitmask)) === false) {\n            throw new \\ErrorException('Error encoding data in JSON format: '.json_last_error());\n        }\n\n        return $encodedString;\n    }\n\n    /**\n     * Filter JSON encode options array against the whitelist array.\n     *\n     * @param array $jsonEncodeOptions\n     *\n     * @return array\n     */\n    protected function filterJsonEncodeOptions(array $jsonEncodeOptions)\n    {\n        return array_intersect($jsonEncodeOptions, $this->jsonEncodeOptionsWhitelist);\n    }\n\n    /**\n     * Sweep JSON encode options together to get options' bitmask.\n     *\n     * @param array $jsonEncodeOptions\n     *\n     * @return int\n     */\n    protected function calucateJsonEncodeOptionsBitmask(array $jsonEncodeOptions)\n    {\n        return array_sum($jsonEncodeOptions);\n    }\n\n    /**\n     * Indent pretty printed JSON string, using given indent style.\n     *\n     * @param string $jsonString\n     * @param string $indentStyle\n     * @param int    $defaultIndentSize\n     *\n     * @return string\n     */\n    protected function indentPrettyPrintedJson($jsonString, $indentStyle, $defaultIndentSize = 2)\n    {\n        $indentChar = $this->getIndentCharForIndentStyle($indentStyle);\n        $indentSize = $this->getPrettyPrintIndentSize() ?: $defaultIndentSize;\n\n        // If the given indentation style is allowed to have various indent size\n        // (number of chars, that are used to indent one level in each line),\n        // indent the JSON string with given (or default) indent size.\n        if ($this->hasVariousIndentSize($indentStyle)) {\n            return $this->peformIndentation($jsonString, $indentChar, $indentSize);\n        }\n\n        // Otherwise following the convention, that indent styles, that does not\n        // allowed to have various indent size (e.g. tab) are indented using\n        // one tabulation character per one indent level in each line.\n        return $this->peformIndentation($jsonString, $indentChar);\n    }\n\n    /**\n     * Get indent char for given indent style.\n     *\n     * @param string $indentStyle\n     *\n     * @return string\n     */\n    protected function getIndentCharForIndentStyle($indentStyle)\n    {\n        return $this->indentChars[$indentStyle];\n    }\n\n    /**\n     * Get indent size for pretty printed JSON string.\n     *\n     * @return int|null\n     */\n    protected function getPrettyPrintIndentSize()\n    {\n        return isset($this->options['indent_size'])\n            ? (int) $this->options['indent_size']\n            : null;\n    }\n\n    /**\n     * Determine if indent style is allowed to have various indent size.\n     *\n     * @param string $indentStyle\n     *\n     * @return bool\n     */\n    protected function hasVariousIndentSize($indentStyle)\n    {\n        return in_array($indentStyle, $this->hasVariousIndentSize);\n    }\n\n    /**\n     * Perform indentation for pretty printed JSON string with a given\n     * indent char, repeated N times, as determined by indent size.\n     *\n     * @param string $jsonString    JSON string, which must be indented\n     * @param string $indentChar    Char, used for indent (default is tab)\n     * @param int    $indentSize    Number of times to repeat indent char per one indent level\n     * @param int    $defaultSpaces Default number of indent spaces after json_encode()\n     *\n     * @return string\n     */\n    protected function peformIndentation($jsonString, $indentChar = \"\\t\", $indentSize = 1, $defaultSpaces = 4)\n    {\n        $pattern = '/(^|\\G) {'.$defaultSpaces.'}/m';\n        $replacement = str_repeat($indentChar, $indentSize).'$1';\n\n        return preg_replace($pattern, $replacement, $jsonString);\n    }\n}\n"
  },
  {
    "path": "src/Http/Response/Format/Jsonp.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Http\\Response\\Format;\n\nclass Jsonp extends Json\n{\n    /**\n     * Name of JSONP callback parameter.\n     *\n     * @var string\n     */\n    protected $callbackName = 'callback';\n\n    /**\n     * Create a new JSONP response formatter instance.\n     *\n     * @param string $callbackName\n     *\n     * @return void\n     */\n    public function __construct($callbackName = 'callback')\n    {\n        $this->callbackName = $callbackName;\n    }\n\n    /**\n     * Determine if a callback is valid.\n     *\n     * @return bool\n     */\n    protected function hasValidCallback()\n    {\n        return $this->request->query->has($this->callbackName);\n    }\n\n    /**\n     * Get the callback from the query string.\n     *\n     * @return string\n     */\n    protected function getCallback()\n    {\n        return $this->request->query->get($this->callbackName);\n    }\n\n    /**\n     * Get the response content type.\n     *\n     * @return string\n     */\n    public function getContentType()\n    {\n        if ($this->hasValidCallback()) {\n            return 'application/javascript';\n        }\n\n        return parent::getContentType();\n    }\n\n    /**\n     * Encode the content to its JSONP representation.\n     *\n     * @param mixed $content\n     *\n     * @return string\n     */\n    protected function encode($content)\n    {\n        $jsonString = parent::encode($content);\n\n        if ($this->hasValidCallback()) {\n            return sprintf('%s(%s);', $this->getCallback(), $jsonString);\n        }\n\n        return $jsonString;\n    }\n}\n"
  },
  {
    "path": "src/Http/Response.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Http;\n\nuse ArrayObject;\nuse Illuminate\\Support\\Str;\nuse UnexpectedValueException;\nuse Illuminate\\Http\\JsonResponse;\nuse Dingo\\Api\\Transformer\\Binding;\nuse Dingo\\Api\\Event\\ResponseIsMorphing;\nuse Dingo\\Api\\Event\\ResponseWasMorphed;\nuse Illuminate\\Contracts\\Support\\Arrayable;\nuse Illuminate\\Http\\Response as IlluminateResponse;\nuse Dingo\\Api\\Transformer\\Factory as TransformerFactory;\nuse Illuminate\\Database\\Eloquent\\Model as EloquentModel;\nuse Illuminate\\Contracts\\Events\\Dispatcher as EventDispatcher;\nuse Illuminate\\Database\\Eloquent\\Collection as EloquentCollection;\nuse Symfony\\Component\\HttpKernel\\Exception\\NotAcceptableHttpException;\n\nclass Response extends IlluminateResponse\n{\n    /**\n     * The exception that triggered the error response.\n     *\n     * @var \\Exception\n     */\n    public $exception;\n\n    /**\n     * Transformer binding instance.\n     *\n     * @var \\Dingo\\Api\\Transformer\\Binding\n     */\n    protected $binding;\n\n    /**\n     * Array of registered formatters.\n     *\n     * @var array\n     */\n    protected static $formatters = [];\n\n    /**\n     * Array of formats' options.\n     *\n     * @var array\n     */\n    protected static $formatsOptions = [];\n\n    /**\n     * Transformer factory instance.\n     *\n     * @var \\Dingo\\Api\\Transformer\\TransformerFactory\n     */\n    protected static $transformer;\n\n    /**\n     * Event dispatcher instance.\n     *\n     * @var \\Illuminate\\Contracts\\Events\\Dispatcher\n     */\n    protected static $events;\n\n    /**\n     * Create a new response instance.\n     *\n     * @param mixed                          $content\n     * @param int                            $status\n     * @param array                          $headers\n     * @param \\Dingo\\Api\\Transformer\\Binding $binding\n     *\n     * @return void\n     */\n    public function __construct($content, $status = 200, $headers = [], Binding $binding = null)\n    {\n        parent::__construct($content, $status, $headers);\n\n        $this->binding = $binding;\n    }\n\n    /**\n     * Make an API response from an existing Illuminate response.\n     *\n     * @param \\Illuminate\\Http\\Response $old\n     *\n     * @return \\Dingo\\Api\\Http\\Response\n     */\n    public static function makeFromExisting(IlluminateResponse $old)\n    {\n        $new = new static($old->getOriginalContent(), $old->getStatusCode());\n\n        $new->headers = $old->headers;\n\n        return $new;\n    }\n\n    /**\n     * Make an API response from an existing JSON response.\n     *\n     * @param \\Illuminate\\Http\\JsonResponse $json\n     *\n     * @return \\Dingo\\Api\\Http\\Response\n     */\n    public static function makeFromJson(JsonResponse $json)\n    {\n        $content = $json->getContent();\n\n        // If the contents of the JsonResponse does not starts with /**/ (typical laravel jsonp response)\n        // we assume that it is a valid json response that can be decoded, or we just use the raw jsonp\n        // contents for building the response\n        if (! Str::startsWith($json->getContent(), '/**/')) {\n            $content = json_decode($json->getContent(), true);\n        }\n\n        $new = new static($content, $json->getStatusCode());\n\n        $new->headers = $json->headers;\n\n        return $new;\n    }\n\n    /**\n     * Morph the API response to the appropriate format.\n     *\n     * @param string $format\n     *\n     * @return \\Dingo\\Api\\Http\\Response\n     */\n    public function morph($format = 'json')\n    {\n        $this->content = $this->getOriginalContent();\n\n        $this->fireMorphingEvent();\n\n        if (isset(static::$transformer) && static::$transformer->transformableResponse($this->content)) {\n            $this->content = static::$transformer->transform($this->content);\n        }\n\n        $formatter = static::getFormatter($format);\n\n        $formatter->setOptions(static::getFormatsOptions($format));\n\n        $defaultContentType = $this->headers->get('Content-Type');\n\n        // If we have no content, we don't want to set this header, as it will be blank\n        $contentType = $formatter->getContentType();\n        if (! empty($contentType)) {\n            $this->headers->set('Content-Type', $formatter->getContentType());\n        }\n\n        $this->fireMorphedEvent();\n\n        if ($this->content instanceof EloquentModel) {\n            $this->content = $formatter->formatEloquentModel($this->content);\n        } elseif ($this->content instanceof EloquentCollection) {\n            $this->content = $formatter->formatEloquentCollection($this->content);\n        } elseif (is_array($this->content) || $this->content instanceof ArrayObject || $this->content instanceof Arrayable) {\n            $this->content = $formatter->formatArray($this->content);\n        } else {\n            if (! empty($defaultContentType)) {\n                $this->headers->set('Content-Type', $defaultContentType);\n            }\n        }\n\n        return $this;\n    }\n\n    /**\n     * Fire the morphed event.\n     *\n     * @return void\n     */\n    protected function fireMorphedEvent()\n    {\n        if (! static::$events) {\n            return;\n        }\n\n        static::$events->dispatch(new ResponseWasMorphed($this, $this->content));\n    }\n\n    /**\n     * Fire the morphing event.\n     *\n     * @return void\n     */\n    protected function fireMorphingEvent()\n    {\n        if (! static::$events) {\n            return;\n        }\n\n        static::$events->dispatch(new ResponseIsMorphing($this, $this->content));\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function setContent($content)\n    {\n        // Attempt to set the content string, if we encounter an unexpected value\n        // then we most likely have an object that cannot be type cast. In that\n        // case we'll simply leave the content as null and set the original\n        // content value and continue.\n        if (! empty($content) && is_object($content) && ! $this->shouldBeJson($content)) {\n            $this->original = $content;\n\n            return $this;\n        }\n\n        try {\n            return parent::setContent($content);\n        } catch (UnexpectedValueException $exception) {\n            $this->original = $content;\n\n            return $this;\n        }\n    }\n\n    /**\n     * Set the event dispatcher instance.\n     *\n     * @param \\Illuminate\\Contracts\\Events\\Dispatcher $events\n     *\n     * @return void\n     */\n    public static function setEventDispatcher(EventDispatcher $events)\n    {\n        static::$events = $events;\n    }\n\n    /**\n     * Get the formatter based on the requested format type.\n     *\n     * @param string $format\n     *\n     * @throws \\RuntimeException\n     *\n     * @return \\Dingo\\Api\\Http\\Response\\Format\\Format\n     */\n    public static function getFormatter($format)\n    {\n        if (! static::hasFormatter($format)) {\n            throw new NotAcceptableHttpException('Unable to format response according to Accept header.');\n        }\n\n        return static::$formatters[$format];\n    }\n\n    /**\n     * Determine if a response formatter has been registered.\n     *\n     * @param string $format\n     *\n     * @return bool\n     */\n    public static function hasFormatter($format)\n    {\n        return isset(static::$formatters[$format]);\n    }\n\n    /**\n     * Set the response formatters.\n     *\n     * @param array $formatters\n     *\n     * @return void\n     */\n    public static function setFormatters(array $formatters)\n    {\n        static::$formatters = $formatters;\n    }\n\n    /**\n     * Set the formats' options.\n     *\n     * @param array $formatsOptions\n     *\n     * @return void\n     */\n    public static function setFormatsOptions(array $formatsOptions)\n    {\n        static::$formatsOptions = $formatsOptions;\n    }\n\n    /**\n     * Get the format's options.\n     *\n     * @param string $format\n     *\n     * @return array\n     */\n    public static function getFormatsOptions($format)\n    {\n        if (! static::hasOptionsForFormat($format)) {\n            return [];\n        }\n\n        return static::$formatsOptions[$format];\n    }\n\n    /**\n     * Determine if any format's options were set.\n     *\n     * @param string $format\n     *\n     * @return bool\n     */\n    public static function hasOptionsForFormat($format)\n    {\n        return isset(static::$formatsOptions[$format]);\n    }\n\n    /**\n     * Add a response formatter.\n     *\n     * @param string                                 $key\n     * @param \\Dingo\\Api\\Http\\Response\\Format\\Format $formatter\n     *\n     * @return void\n     */\n    public static function addFormatter($key, $formatter)\n    {\n        static::$formatters[$key] = $formatter;\n    }\n\n    /**\n     * Set the transformer factory instance.\n     *\n     * @param \\Dingo\\Api\\Transformer\\Factory $transformer\n     *\n     * @return void\n     */\n    public static function setTransformer(TransformerFactory $transformer)\n    {\n        static::$transformer = $transformer;\n    }\n\n    /**\n     * Get the transformer instance.\n     *\n     * @return \\Dingo\\Api\\Transformer\\Factory\n     */\n    public static function getTransformer()\n    {\n        return static::$transformer;\n    }\n\n    /**\n     * Add a meta key and value pair.\n     *\n     * @param string $key\n     * @param mixed  $value\n     *\n     * @return \\Dingo\\Api\\Http\\Response\n     */\n    public function addMeta($key, $value)\n    {\n        $this->binding->addMeta($key, $value);\n\n        return $this;\n    }\n\n    /**\n     * Add a meta key and value pair.\n     *\n     * @param string $key\n     * @param mixed  $value\n     *\n     * @return \\Dingo\\Api\\Http\\Response\n     */\n    public function meta($key, $value)\n    {\n        return $this->addMeta($key, $value);\n    }\n\n    /**\n     * Set the meta data for the response.\n     *\n     * @param array $meta\n     *\n     * @return \\Dingo\\Api\\Http\\Response\n     */\n    public function setMeta(array $meta)\n    {\n        $this->binding->setMeta($meta);\n\n        return $this;\n    }\n\n    /**\n     * Get the meta data for the response.\n     *\n     * @return array\n     */\n    public function getMeta()\n    {\n        return $this->binding->getMeta();\n    }\n\n    /**\n     * Add a cookie to the response.\n     *\n     * @param \\Symfony\\Component\\HttpFoundation\\Cookie|mixed $cookie\n     *\n     * @return \\Dingo\\Api\\Http\\Response\n     */\n    public function cookie($cookie)\n    {\n        return $this->withCookie($cookie);\n    }\n\n    /**\n     * Add a header to the response.\n     *\n     * @param string $key\n     * @param string $value\n     * @param bool   $replace\n     *\n     * @return \\Dingo\\Api\\Http\\Response\n     */\n    public function withHeader($key, $value, $replace = true)\n    {\n        return $this->header($key, $value, $replace);\n    }\n\n    /**\n     * Set the response status code.\n     *\n     * @param int $statusCode\n     *\n     * @return \\Dingo\\Api\\Http\\Response\n     */\n    public function statusCode($statusCode)\n    {\n        return $this->setStatusCode($statusCode);\n    }\n}\n"
  },
  {
    "path": "src/Http/Validation/Accept.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Http\\Validation;\n\nuse Illuminate\\Http\\Request;\nuse Dingo\\Api\\Contract\\Http\\Validator;\nuse Dingo\\Api\\Http\\Parser\\Accept as AcceptParser;\nuse Symfony\\Component\\HttpKernel\\Exception\\BadRequestHttpException;\n\nclass Accept implements Validator\n{\n    /**\n     * Accept parser instance.\n     *\n     * @var \\Dingo\\Api\\Http\\Parser\\Accept\n     */\n    protected $accept;\n\n    /**\n     * Indicates if the accept matching is strict.\n     *\n     * @var bool\n     */\n    protected $strict;\n\n    /**\n     * Create a new accept validator instance.\n     *\n     * @param \\Dingo\\Api\\Http\\Parser\\Accept $accept\n     * @param bool                          $strict\n     *\n     * @return void\n     */\n    public function __construct(AcceptParser $accept, $strict = false)\n    {\n        $this->accept = $accept;\n        $this->strict = $strict;\n    }\n\n    /**\n     * Validate the accept header on the request. If this fails it will throw\n     * an HTTP exception that will be caught by the middleware. This\n     * validator should always be run last and must not return\n     * a success boolean.\n     *\n     * @param \\Illuminate\\Http\\Request $request\n     *\n     * @throws \\Exception|\\Symfony\\Component\\HttpKernel\\Exception\\BadRequestHttpException\n     *\n     * @return bool\n     */\n    public function validate(Request $request)\n    {\n        try {\n            $this->accept->parse($request, $this->strict);\n        } catch (BadRequestHttpException $exception) {\n            if ($request->getMethod() === 'OPTIONS') {\n                return true;\n            }\n\n            throw $exception;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Http/Validation/Domain.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Http\\Validation;\n\nuse Illuminate\\support\\Str;\nuse Illuminate\\Http\\Request;\nuse Dingo\\Api\\Contract\\Http\\Validator;\n\nclass Domain implements Validator\n{\n    const PATTERN_STRIP_PROTOCOL = '/:\\d*$/';\n\n    /**\n     * API domain.\n     *\n     * @var string\n     */\n    protected $domain;\n\n    /**\n     * Create a new domain validator instance.\n     *\n     * @param string $domain\n     *\n     * @return void\n     */\n    public function __construct($domain)\n    {\n        $this->domain = $domain;\n    }\n\n    /**\n     * Validate that the request domain matches the configured domain.\n     *\n     * @param \\Illuminate\\Http\\Request $request\n     *\n     * @return bool\n     */\n    public function validate(Request $request)\n    {\n        return ! is_null($this->domain) && $request->getHost() === $this->getStrippedDomain();\n    }\n\n    /**\n     * Strip the protocol from a domain.\n     *\n     * @param string $domain\n     *\n     * @return string\n     */\n    protected function stripProtocol($domain)\n    {\n        if (Str::contains($domain, '://')) {\n            $domain = substr($domain, strpos($domain, '://') + 3);\n        }\n\n        return $domain;\n    }\n\n    /**\n     * Strip the port from a domain.\n     *\n     * @param $domain\n     *\n     * @return mixed\n     */\n    protected function stripPort($domain)\n    {\n        if ($domainStripped = preg_replace(self::PATTERN_STRIP_PROTOCOL, null, $domain)) {\n            return $domainStripped;\n        }\n\n        return $domain;\n    }\n\n    /**\n     * Get the domain stripped from protocol and port.\n     *\n     * @return mixed\n     */\n    protected function getStrippedDomain()\n    {\n        return $this->stripPort($this->stripProtocol($this->domain));\n    }\n}\n"
  },
  {
    "path": "src/Http/Validation/Prefix.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Http\\Validation;\n\nuse Illuminate\\Http\\Request;\nuse Dingo\\Api\\Contract\\Http\\Validator;\n\nclass Prefix implements Validator\n{\n    /**\n     * API prefix.\n     *\n     * @var string\n     */\n    protected $prefix;\n\n    /**\n     * Create a new prefix validator instance.\n     *\n     * @param string $prefix\n     *\n     * @return void\n     */\n    public function __construct($prefix)\n    {\n        $this->prefix = $prefix;\n    }\n\n    /**\n     * Validate the request has a prefix and if it matches the configured\n     * API prefix.\n     *\n     * @param \\Illuminate\\Http\\Request $request\n     *\n     * @return bool\n     */\n    public function validate(Request $request)\n    {\n        $prefix = $this->filterAndExplode($this->prefix);\n\n        $path = $this->filterAndExplode($request->getPathInfo());\n\n        return ! is_null($this->prefix) && $prefix == array_slice($path, 0, count($prefix));\n    }\n\n    /**\n     * Explode array on slash and remove empty values.\n     *\n     * @param array $array\n     *\n     * @return array\n     */\n    protected function filterAndExplode($array)\n    {\n        return array_filter(explode('/', $array));\n    }\n}\n"
  },
  {
    "path": "src/Provider/DingoServiceProvider.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Provider;\n\nuse RuntimeException;\nuse Dingo\\Api\\Auth\\Auth;\nuse Dingo\\Api\\Dispatcher;\nuse Dingo\\Api\\Http\\Request;\nuse Dingo\\Api\\Http\\Response;\nuse Dingo\\Api\\Console\\Command;\nuse Dingo\\Api\\Exception\\Handler as ExceptionHandler;\nuse Dingo\\Api\\Transformer\\Factory as TransformerFactory;\n\nclass DingoServiceProvider extends ServiceProvider\n{\n    /**\n     * Boot the service provider.\n     *\n     * @return void\n     */\n    public function boot()\n    {\n        $this->setResponseStaticInstances();\n\n        Request::setAcceptParser($this->app[\\Dingo\\Api\\Http\\Parser\\Accept::class]);\n\n        $this->app->rebinding('api.routes', function ($app, $routes) {\n            $app['api.url']->setRouteCollections($routes);\n        });\n    }\n\n    protected function setResponseStaticInstances()\n    {\n        Response::setFormatters($this->config('formats'));\n        Response::setFormatsOptions($this->config('formatsOptions'));\n        Response::setTransformer($this->app['api.transformer']);\n        Response::setEventDispatcher($this->app['events']);\n    }\n\n    /**\n     * Register the service provider.\n     *\n     * @return void\n     */\n    public function register()\n    {\n        $this->registerConfig();\n\n        $this->registerClassAliases();\n\n        $this->app->register(RoutingServiceProvider::class);\n\n        $this->app->register(HttpServiceProvider::class);\n\n        $this->registerExceptionHandler();\n\n        $this->registerDispatcher();\n\n        $this->registerAuth();\n\n        $this->registerTransformer();\n\n        $this->registerDocsCommand();\n\n        if (class_exists('Illuminate\\Foundation\\Application', false)) {\n            $this->commands([\n                \\Dingo\\Api\\Console\\Command\\Cache::class,\n                \\Dingo\\Api\\Console\\Command\\Routes::class,\n            ]);\n        }\n    }\n\n    /**\n     * Register the configuration.\n     *\n     * @return void\n     */\n    protected function registerConfig()\n    {\n        $this->mergeConfigFrom(realpath(__DIR__.'/../../config/api.php'), 'api');\n\n        if (! $this->app->runningInConsole() && empty($this->config('prefix')) && empty($this->config('domain'))) {\n            throw new RuntimeException('Unable to boot ApiServiceProvider, configure an API domain or prefix.');\n        }\n    }\n\n    /**\n     * Register the class aliases.\n     *\n     * @return void\n     */\n    protected function registerClassAliases()\n    {\n        $serviceAliases = [\n            \\Dingo\\Api\\Http\\Request::class => \\Dingo\\Api\\Contract\\Http\\Request::class,\n            'api.dispatcher' => \\Dingo\\Api\\Dispatcher::class,\n            'api.http.validator' => \\Dingo\\Api\\Http\\RequestValidator::class,\n            'api.http.response' => \\Dingo\\Api\\Http\\Response\\Factory::class,\n            'api.router' => \\Dingo\\Api\\Routing\\Router::class,\n            'api.router.adapter' => \\Dingo\\Api\\Contract\\Routing\\Adapter::class,\n            'api.auth' => \\Dingo\\Api\\Auth\\Auth::class,\n            'api.limiting' => \\Dingo\\Api\\Http\\RateLimit\\Handler::class,\n            'api.transformer' => \\Dingo\\Api\\Transformer\\Factory::class,\n            'api.url' => \\Dingo\\Api\\Routing\\UrlGenerator::class,\n            'api.exception' => [\\Dingo\\Api\\Exception\\Handler::class, \\Dingo\\Api\\Contract\\Debug\\ExceptionHandler::class],\n        ];\n\n        foreach ($serviceAliases as $key => $aliases) {\n            foreach ((array) $aliases as $alias) {\n                $this->app->alias($key, $alias);\n            }\n        }\n    }\n\n    /**\n     * Register the exception handler.\n     *\n     * @return void\n     */\n    protected function registerExceptionHandler()\n    {\n        $this->app->singleton('api.exception', function ($app) {\n            return new ExceptionHandler($app['Illuminate\\Contracts\\Debug\\ExceptionHandler'], $this->config('errorFormat'), $this->config('debug'));\n        });\n    }\n\n    /**\n     * Register the internal dispatcher.\n     *\n     * @return void\n     */\n    public function registerDispatcher()\n    {\n        $this->app->singleton('api.dispatcher', function ($app) {\n            $dispatcher = new Dispatcher($app, $app['files'], $app[\\Dingo\\Api\\Routing\\Router::class], $app[\\Dingo\\Api\\Auth\\Auth::class]);\n\n            $dispatcher->setSubtype($this->config('subtype'));\n            $dispatcher->setStandardsTree($this->config('standardsTree'));\n            $dispatcher->setPrefix($this->config('prefix'));\n            $dispatcher->setDefaultVersion($this->config('version'));\n            $dispatcher->setDefaultDomain($this->config('domain'));\n            $dispatcher->setDefaultFormat($this->config('defaultFormat'));\n\n            return $dispatcher;\n        });\n    }\n\n    /**\n     * Register the auth.\n     *\n     * @return void\n     */\n    protected function registerAuth()\n    {\n        $this->app->singleton('api.auth', function ($app) {\n            return new Auth($app[\\Dingo\\Api\\Routing\\Router::class], $app, $this->config('auth'));\n        });\n    }\n\n    /**\n     * Register the transformer factory.\n     *\n     * @return void\n     */\n    protected function registerTransformer()\n    {\n        $this->app->singleton('api.transformer', function ($app) {\n            return new TransformerFactory($app, $this->config('transformer'));\n        });\n    }\n\n    /**\n     * Register the documentation command.\n     *\n     * @return void\n     */\n    protected function registerDocsCommand()\n    {\n        $this->app->singleton(\\Dingo\\Api\\Console\\Command\\Docs::class, function ($app) {\n            return new Command\\Docs(\n                $app[\\Dingo\\Api\\Routing\\Router::class],\n                $app[\\Dingo\\Blueprint\\Blueprint::class],\n                $app[\\Dingo\\Blueprint\\Writer::class],\n                $this->config('name'),\n                $this->config('version')\n            );\n        });\n\n        $this->commands([\\Dingo\\Api\\Console\\Command\\Docs::class]);\n    }\n}\n"
  },
  {
    "path": "src/Provider/HttpServiceProvider.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Provider;\n\nuse Dingo\\Api\\Auth\\Auth;\nuse Dingo\\Api\\Routing\\Router;\nuse Dingo\\Api\\Http\\Middleware;\nuse Dingo\\Api\\Http\\Validation;\nuse Dingo\\Api\\Transformer\\Factory;\nuse Dingo\\Api\\Http\\RequestValidator;\nuse Dingo\\Api\\Http\\RateLimit\\Handler;\nuse Dingo\\Api\\Http\\Validation\\Accept;\nuse Dingo\\Api\\Http\\Validation\\Domain;\nuse Dingo\\Api\\Http\\Validation\\Prefix;\nuse Dingo\\Api\\Http\\Middleware\\Request;\nuse Dingo\\Api\\Http\\Middleware\\RateLimit;\nuse Dingo\\Api\\Contract\\Debug\\ExceptionHandler;\nuse Dingo\\Api\\Http\\Middleware\\PrepareController;\nuse Dingo\\Api\\Http\\Parser\\Accept as AcceptParser;\nuse Dingo\\Api\\Http\\Middleware\\Auth as AuthMiddleware;\nuse Dingo\\Api\\Http\\Response\\Factory as ResponseFactory;\nuse Dingo\\Api\\Http\\RateLimit\\Handler as RateLimitHandler;\n\nclass HttpServiceProvider extends ServiceProvider\n{\n    /**\n     * Register the service provider.\n     *\n     * @return void\n     */\n    public function register()\n    {\n        $this->registerRateLimiting();\n\n        $this->registerHttpValidation();\n\n        $this->registerHttpParsers();\n\n        $this->registerResponseFactory();\n\n        $this->registerMiddleware();\n    }\n\n    /**\n     * Register the rate limiting.\n     *\n     * @return void\n     */\n    protected function registerRateLimiting()\n    {\n        $this->app->singleton('api.limiting', function ($app) {\n            return new RateLimitHandler($app, $app['cache'], $this->config('throttling'));\n        });\n    }\n\n    /**\n     * Register the HTTP validation.\n     *\n     * @return void\n     */\n    protected function registerHttpValidation()\n    {\n        $this->app->singleton('api.http.validator', function ($app) {\n            return new RequestValidator($app);\n        });\n\n        $this->app->singleton(Domain::class, function ($app) {\n            return new Validation\\Domain($this->config('domain'));\n        });\n\n        $this->app->singleton(Prefix::class, function ($app) {\n            return new Validation\\Prefix($this->config('prefix'));\n        });\n\n        $this->app->singleton(Accept::class, function ($app) {\n            return new Validation\\Accept(\n                $this->app[AcceptParser::class],\n                $this->config('strict')\n            );\n        });\n    }\n\n    /**\n     * Register the HTTP parsers.\n     *\n     * @return void\n     */\n    protected function registerHttpParsers()\n    {\n        $this->app->singleton(AcceptParser::class, function ($app) {\n            return new AcceptParser(\n                $this->config('standardsTree'),\n                $this->config('subtype'),\n                $this->config('version'),\n                $this->config('defaultFormat')\n            );\n        });\n    }\n\n    /**\n     * Register the response factory.\n     *\n     * @return void\n     */\n    protected function registerResponseFactory()\n    {\n        $this->app->singleton('api.http.response', function ($app) {\n            return new ResponseFactory($app[Factory::class]);\n        });\n    }\n\n    /**\n     * Register the middleware.\n     *\n     * @return void\n     */\n    protected function registerMiddleware()\n    {\n        $this->app->singleton(Request::class, function ($app) {\n            $middleware = new Middleware\\Request(\n                $app,\n                $app[ExceptionHandler::class],\n                $app[Router::class],\n                $app[RequestValidator::class],\n                $app['events']\n            );\n\n            $middleware->setMiddlewares($this->config('middleware', false));\n\n            return $middleware;\n        });\n\n        $this->app->singleton(AuthMiddleware::class, function ($app) {\n            return new Middleware\\Auth($app[Router::class], $app[Auth::class]);\n        });\n\n        $this->app->singleton(RateLimit::class, function ($app) {\n            return new Middleware\\RateLimit($app[Router::class], $app[Handler::class]);\n        });\n\n        $this->app->singleton(PrepareController::class, function ($app) {\n            return new Middleware\\PrepareController($app[Router::class]);\n        });\n    }\n}\n"
  },
  {
    "path": "src/Provider/LaravelServiceProvider.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Provider;\n\nuse ReflectionClass;\nuse Dingo\\Api\\Http\\FormRequest;\nuse Illuminate\\Routing\\Redirector;\nuse Dingo\\Api\\Http\\Middleware\\Auth;\nuse Illuminate\\Contracts\\Http\\Kernel;\nuse Dingo\\Api\\Event\\RequestWasMatched;\nuse Dingo\\Api\\Http\\Middleware\\Request;\nuse Illuminate\\Foundation\\Application;\nuse Dingo\\Api\\Http\\Middleware\\RateLimit;\nuse Illuminate\\Routing\\ControllerDispatcher;\nuse Dingo\\Api\\Http\\Middleware\\PrepareController;\nuse Illuminate\\Http\\Request as IlluminateRequest;\nuse Dingo\\Api\\Routing\\Adapter\\Laravel as LaravelAdapter;\nuse Illuminate\\Contracts\\Validation\\ValidatesWhenResolved;\n\nclass LaravelServiceProvider extends DingoServiceProvider\n{\n    /**\n     * Boot the service provider.\n     *\n     * @return void\n     */\n    public function boot()\n    {\n        parent::boot();\n\n        $this->publishes([realpath(__DIR__.'/../../config/api.php') => config_path('api.php')]);\n\n        $kernel = $this->app->make(Kernel::class);\n\n        $this->app[Request::class]->mergeMiddlewares(\n            $this->gatherAppMiddleware($kernel)\n        );\n\n        $this->addRequestMiddlewareToBeginning($kernel);\n\n        $this->app['events']->listen(RequestWasMatched::class, function (RequestWasMatched $event) {\n            $this->replaceRouteDispatcher();\n\n            $this->updateRouterBindings();\n        });\n\n        // Originally Validate FormRequest after resolving\n        /* This casues the prepareForValidation() function to be called twice, and seemingly has no other benefit, see discussion at\n        https://github.com/dingo/api/issues/1668\n        This is already done by laravel service provider, and works with Dingo router\n        $this->app->afterResolving(ValidatesWhenResolved::class, function ($resolved) {\n            $resolved->validateResolved();\n        });\n        */\n\n        $this->app->resolving(FormRequest::class, function (FormRequest $request, Application $app) {\n            $this->initializeRequest($request, $app['request']);\n\n            $request->setContainer($app)->setRedirector($app->make(Redirector::class));\n        });\n\n        $this->addMiddlewareAlias('api.auth', Auth::class);\n        $this->addMiddlewareAlias('api.throttle', RateLimit::class);\n        $this->addMiddlewareAlias('api.controllers', PrepareController::class);\n    }\n\n    /**\n     * Replace the route dispatcher.\n     *\n     * @return void\n     */\n    protected function replaceRouteDispatcher()\n    {\n        $this->app->singleton('illuminate.route.dispatcher', function ($app) {\n            return new ControllerDispatcher($app['api.router.adapter']->getRouter(), $app);\n        });\n    }\n\n    /**\n     * Grab the bindings from the Laravel router and set them on the adapters\n     * router.\n     *\n     * @return void\n     */\n    protected function updateRouterBindings()\n    {\n        foreach ($this->getRouterBindings() as $key => $binding) {\n            $this->app['api.router.adapter']->getRouter()->bind($key, $binding);\n        }\n    }\n\n    /**\n     * Get the Laravel routers bindings.\n     *\n     * @return array\n     */\n    protected function getRouterBindings()\n    {\n        $property = (new ReflectionClass($this->app['router']))->getProperty('binders');\n        $property->setAccessible(true);\n\n        return $property->getValue($this->app['router']);\n    }\n\n    /**\n     * Register the service provider.\n     *\n     * @return void\n     */\n    public function register()\n    {\n        parent::register();\n\n        $this->registerRouterAdapter();\n    }\n\n    /**\n     * Register the router adapter.\n     *\n     * @return void\n     */\n    protected function registerRouterAdapter()\n    {\n        $this->app->singleton('api.router.adapter', function ($app) {\n            return new LaravelAdapter($app['router']);\n        });\n    }\n\n    /**\n     * Add the request middleware to the beginning of the kernel.\n     *\n     * @param \\Illuminate\\Contracts\\Http\\Kernel $kernel\n     *\n     * @return void\n     */\n    protected function addRequestMiddlewareToBeginning(Kernel $kernel)\n    {\n        $kernel->prependMiddleware(Request::class);\n    }\n\n    /**\n     * Register a short-hand name for a middleware. For compatibility\n     * with Laravel < 5.4 check if aliasMiddleware exists since this\n     * method has been renamed.\n     *\n     * @param string $name\n     * @param string $class\n     *\n     * @return void\n     */\n    protected function addMiddlewareAlias($name, $class)\n    {\n        $router = $this->app['router'];\n\n        if (method_exists($router, 'aliasMiddleware')) {\n            return $router->aliasMiddleware($name, $class);\n        }\n\n        return $router->middleware($name, $class);\n    }\n\n    /**\n     * Gather the application middleware besides this one so that we can send\n     * our request through them, exactly how the developer wanted.\n     *\n     * @param \\Illuminate\\Contracts\\Http\\Kernel $kernel\n     *\n     * @return array\n     */\n    protected function gatherAppMiddleware(Kernel $kernel)\n    {\n        $property = (new ReflectionClass($kernel))->getProperty('middleware');\n        $property->setAccessible(true);\n\n        return $property->getValue($kernel);\n    }\n\n    /**\n     * Initialize the form request with data from the given request.\n     *\n     * @param FormRequest $form\n     * @param IlluminateRequest $current\n     *\n     * @return void\n     */\n    protected function initializeRequest(FormRequest $form, IlluminateRequest $current)\n    {\n        $files = $current->files->all();\n\n        $files = is_array($files) ? array_filter($files) : $files;\n\n        $form->initialize(\n            $current->query->all(),\n            $current->request->all(),\n            $current->attributes->all(),\n            $current->cookies->all(),\n            $files,\n            $current->server->all(),\n            $current->getContent()\n        );\n\n        $form->setJson($current->json());\n\n        if ($session = $current->getSession()) {\n            $form->setLaravelSession($session);\n        }\n\n        $form->setUserResolver($current->getUserResolver());\n\n        $form->setRouteResolver($current->getRouteResolver());\n    }\n}\n"
  },
  {
    "path": "src/Provider/LumenServiceProvider.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Provider;\n\nuse ReflectionClass;\nuse Laravel\\Lumen\\Application;\nuse Dingo\\Api\\Http\\FormRequest;\nuse Laravel\\Lumen\\Http\\Redirector;\nuse Dingo\\Api\\Http\\Middleware\\Auth;\nuse Dingo\\Api\\Http\\Middleware\\Request;\nuse Dingo\\Api\\Http\\Middleware\\RateLimit;\nuse FastRoute\\Dispatcher\\GroupCountBased;\nuse Dingo\\Api\\Http\\Middleware\\PrepareController;\nuse FastRoute\\RouteParser\\Std as StdRouteParser;\nuse Illuminate\\Http\\Request as IlluminateRequest;\nuse Dingo\\Api\\Routing\\Adapter\\Lumen as LumenAdapter;\nuse Illuminate\\Contracts\\Validation\\ValidatesWhenResolved;\nuse FastRoute\\DataGenerator\\GroupCountBased as GcbDataGenerator;\n\nclass LumenServiceProvider extends DingoServiceProvider\n{\n    /**\n     * Boot the service provider.\n     *\n     * @throws \\ReflectionException\n     *\n     * @return void\n     */\n    public function boot()\n    {\n        parent::boot();\n\n        $this->app->configure('api');\n\n        $reflection = new ReflectionClass($this->app);\n\n        $this->app[Request::class]->mergeMiddlewares(\n            $this->gatherAppMiddleware($reflection)\n        );\n\n        $this->addRequestMiddlewareToBeginning($reflection);\n\n        // Because Lumen sets the route resolver at a very weird point we're going to\n        // have to use reflection whenever the request instance is rebound to\n        // set the route resolver to get the current route.\n        $this->app->rebinding(IlluminateRequest::class, function ($app, $request) {\n            $request->setRouteResolver(function () use ($app) {\n                $reflection = new ReflectionClass($app);\n\n                $property = $reflection->getProperty('currentRoute');\n                $property->setAccessible(true);\n\n                return $property->getValue($app);\n            });\n        });\n\n        // Validate FormRequest after resolving\n        $this->app->afterResolving(ValidatesWhenResolved::class, function ($resolved) {\n            $resolved->validateResolved();\n        });\n\n        $this->app->resolving(FormRequest::class, function (FormRequest $request, Application $app) {\n            $this->initializeRequest($request, $app['request']);\n\n            $request->setContainer($app)->setRedirector($app->make(Redirector::class));\n        });\n\n        $this->app->routeMiddleware([\n            'api.auth' => Auth::class,\n            'api.throttle' => RateLimit::class,\n            'api.controllers' => PrepareController::class,\n        ]);\n    }\n\n    /**\n     * Setup the configuration.\n     *\n     * @return void\n     */\n    protected function setupConfig()\n    {\n        $this->app->configure('api');\n\n        parent::setupConfig();\n    }\n\n    /**\n     * Register the service provider.\n     *\n     * @return void\n     */\n    public function register()\n    {\n        parent::register();\n\n        $this->app->singleton('api.router.adapter', function ($app) {\n            return new LumenAdapter($app, new StdRouteParser, new GcbDataGenerator, $this->getDispatcherResolver());\n        });\n    }\n\n    /**\n     * Get the dispatcher resolver callback.\n     *\n     * @return \\Closure\n     */\n    protected function getDispatcherResolver()\n    {\n        return function ($routeCollector) {\n            return new GroupCountBased($routeCollector->getData());\n        };\n    }\n\n    /**\n     * Add the request middleware to the beginning of the middleware stack on the\n     * Lumen application instance.\n     *\n     * @param \\ReflectionClass $reflection\n     *\n     * @return void\n     */\n    protected function addRequestMiddlewareToBeginning(ReflectionClass $reflection)\n    {\n        $property = $reflection->getProperty('middleware');\n        $property->setAccessible(true);\n\n        $middleware = $property->getValue($this->app);\n\n        array_unshift($middleware, Request::class);\n\n        $property->setValue($this->app, $middleware);\n        $property->setAccessible(false);\n    }\n\n    /**\n     * Gather the application middleware besides this one so that we can send\n     * our request through them, exactly how the developer wanted.\n     *\n     * @param \\ReflectionClass $reflection\n     *\n     * @return array\n     */\n    protected function gatherAppMiddleware(ReflectionClass $reflection)\n    {\n        $property = $reflection->getProperty('middleware');\n        $property->setAccessible(true);\n\n        $middleware = $property->getValue($this->app);\n\n        return $middleware;\n    }\n\n    /**\n     * Initialize the form request with data from the given request.\n     *\n     * @param FormRequest $form\n     * @param IlluminateRequest $current\n     *\n     * @return void\n     */\n    protected function initializeRequest(FormRequest $form, IlluminateRequest $current)\n    {\n        $files = $current->files->all();\n\n        $files = is_array($files) ? array_filter($files) : $files;\n\n        $form->initialize(\n            $current->query->all(),\n            $current->request->all(),\n            $current->attributes->all(),\n            $current->cookies->all(),\n            $files,\n            $current->server->all(),\n            $current->getContent()\n        );\n\n        $form->setJson($current->json());\n\n        if ($session = $current->getSession()) {\n            $form->setLaravelSession($session);\n        }\n\n        $form->setUserResolver($current->getUserResolver());\n\n        $form->setRouteResolver($current->getRouteResolver());\n    }\n}\n"
  },
  {
    "path": "src/Provider/RoutingServiceProvider.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Provider;\n\nuse Dingo\\Api\\Routing\\Router;\nuse Dingo\\Api\\Routing\\UrlGenerator;\nuse Dingo\\Api\\Contract\\Routing\\Adapter;\nuse Dingo\\Api\\Routing\\ResourceRegistrar;\nuse Dingo\\Api\\Contract\\Debug\\ExceptionHandler;\n\nclass RoutingServiceProvider extends ServiceProvider\n{\n    /**\n     * Register the service provider.\n     */\n    public function register()\n    {\n        $this->registerRouter();\n\n        $this->registerUrlGenerator();\n    }\n\n    /**\n     * Register the router.\n     */\n    protected function registerRouter()\n    {\n        $this->app->singleton('api.router', function ($app) {\n            $router = new Router(\n                $app[Adapter::class],\n                $app[ExceptionHandler::class],\n                $app,\n                $this->config('domain'),\n                $this->config('prefix')\n            );\n\n            $router->setConditionalRequest($this->config('conditionalRequest'));\n\n            return $router;\n        });\n\n        $this->app->singleton(ResourceRegistrar::class, function ($app) {\n            return new ResourceRegistrar($app[Router::class]);\n        });\n    }\n\n    /**\n     * Register the URL generator.\n     */\n    protected function registerUrlGenerator()\n    {\n        $this->app->singleton('api.url', function ($app) {\n            $url = new UrlGenerator($app['request']);\n\n            $url->setRouteCollections($app[Router::class]->getRoutes());\n\n            $url->setKeyResolver(function () {\n                return $this->app->make('config')->get('app.key');\n            });\n\n            return $url;\n        });\n    }\n\n    /**\n     * Get the URL generator request rebinder.\n     *\n     * @return \\Closure\n     */\n    private function requestRebinder()\n    {\n        return function ($app, $request) {\n            $app['api.url']->setRequest($request);\n        };\n    }\n}\n"
  },
  {
    "path": "src/Provider/ServiceProvider.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Provider;\n\nuse Illuminate\\Support\\ServiceProvider as IlluminateServiceProvider;\n\nabstract class ServiceProvider extends IlluminateServiceProvider\n{\n    /**\n     * Array of config items that are instantiable.\n     *\n     * @var array\n     */\n    protected $instantiable = [\n        'middleware', 'auth', 'throttling', 'transformer', 'formats',\n    ];\n\n    /**\n     * Retrieve and instantiate a config value if it exists and is a class.\n     *\n     * @param string $item\n     * @param bool   $instantiate\n     *\n     * @return mixed\n     */\n    protected function config($item, $instantiate = true)\n    {\n        $value = $this->app['config']->get('api.'.$item);\n\n        if (is_array($value)) {\n            return $instantiate ? $this->instantiateConfigValues($item, $value) : $value;\n        }\n\n        return $instantiate ? $this->instantiateConfigValue($item, $value) : $value;\n    }\n\n    /**\n     * Instantiate an array of instantiable configuration values.\n     *\n     * @param string $item\n     * @param array  $values\n     *\n     * @return array\n     */\n    protected function instantiateConfigValues($item, array $values)\n    {\n        foreach ($values as $key => $value) {\n            $values[$key] = $this->instantiateConfigValue($item, $value);\n        }\n\n        return $values;\n    }\n\n    /**\n     * Instantiate an instantiable configuration value.\n     *\n     * @param string $item\n     * @param mixed  $value\n     *\n     * @return mixed\n     */\n    protected function instantiateConfigValue($item, $value)\n    {\n        if (is_string($value) && in_array($item, $this->instantiable)) {\n            return $this->app->make($value);\n        }\n\n        return $value;\n    }\n}\n"
  },
  {
    "path": "src/Routing/Adapter/Laravel.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Routing\\Adapter;\n\nuse Dingo\\Api\\Contract\\Routing\\Adapter;\nuse Dingo\\Api\\Exception\\UnknownVersionException;\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Routing\\Route;\nuse Illuminate\\Routing\\RouteCollection;\nuse Illuminate\\Routing\\Router;\n\nclass Laravel implements Adapter\n{\n    /**\n     * Application container instance.\n     *\n     * @var \\Illuminate\\Contracts\\Container\\Container\n     */\n    protected $container;\n\n    /**\n     * Laravel router instance.\n     *\n     * @var \\Illuminate\\Routing\\Router\n     */\n    protected $router;\n\n    /**\n     * Array of registered routes.\n     *\n     * @var array\n     */\n    protected $routes = [];\n\n    /**\n     * Array of merged old routes and API routes.\n     *\n     * @var array\n     */\n    protected $mergedRoutes = [];\n\n    /**\n     * Routes already defined on the router.\n     *\n     * @var \\Illuminate\\Routing\\RouteCollection\n     */\n    protected $oldRoutes;\n\n    /**\n     * The globally available parameter patterns.\n     *\n     * @var array\n     */\n    protected $patterns = [];\n\n    /**\n     * Create a new laravel routing adapter instance.\n     *\n     * @param \\Illuminate\\Routing\\Router $router\n     *\n     * @return void\n     */\n    public function __construct(Router $router)\n    {\n        $this->router = $router;\n    }\n\n    /**\n     * Dispatch a request.\n     *\n     * @param \\Illuminate\\Http\\Request $request\n     * @param string                   $version\n     *\n     * @return mixed\n     */\n    public function dispatch(Request $request, $version)\n    {\n        if (! isset($this->routes[$version])) {\n            throw new UnknownVersionException;\n        }\n\n        $routes = $this->mergeOldRoutes($version);\n\n        $this->router->setRoutes($routes);\n\n        $router = clone $this->router;\n\n        $response = $router->dispatch($request);\n\n        unset($router);\n\n        return $response;\n    }\n\n    /**\n     * Merge the old application routes with the API routes.\n     *\n     * @param string $version\n     *\n     * @return array\n     */\n    protected function mergeOldRoutes($version)\n    {\n        if (! isset($this->oldRoutes)) {\n            $this->oldRoutes = $this->router->getRoutes();\n        }\n\n        if (! isset($this->mergedRoutes[$version])) {\n            $this->mergedRoutes[$version] = $this->routes[$version];\n\n            foreach ($this->oldRoutes as $route) {\n                $this->mergedRoutes[$version]->add($route);\n            }\n\n            $this->mergedRoutes[$version]->refreshNameLookups();\n            $this->mergedRoutes[$version]->refreshActionLookups();\n        }\n\n        return $this->mergedRoutes[$version];\n    }\n\n    /**\n     * Get the URI, methods, and action from the route.\n     *\n     * @param mixed                    $route\n     * @param \\Illuminate\\Http\\Request $request\n     *\n     * @return array\n     */\n    public function getRouteProperties($route, Request $request)\n    {\n        if (method_exists($route, 'uri') && method_exists($route, 'methods')) {\n            return [$route->uri(), $route->methods(), $route->getAction()];\n        }\n\n        return [$route->getUri(), $route->getMethods(), $route->getAction()];\n    }\n\n    /**\n     * Add a route to the appropriate route collection.\n     *\n     * @param array  $methods\n     * @param array  $versions\n     * @param string $uri\n     * @param mixed  $action\n     *\n     * @return \\Illuminate\\Routing\\Route\n     */\n    public function addRoute(array $methods, array $versions, $uri, $action)\n    {\n        $this->createRouteCollections($versions);\n\n        // Add where-patterns from original laravel router\n        $action['where'] = array_merge($this->router->getPatterns(), $action['where'] ?? []);\n\n        $route = new Route($methods, $uri, $action);\n        $route->where($action['where']);\n\n        foreach ($versions as $version) {\n            $this->routes[$version]->add($route);\n        }\n\n        return $route;\n    }\n\n    /**\n     * Create the route collections for the versions.\n     *\n     * @param array $versions\n     *\n     * @return void\n     */\n    protected function createRouteCollections(array $versions)\n    {\n        foreach ($versions as $version) {\n            if (! isset($this->routes[$version])) {\n                $this->routes[$version] = new RouteCollection;\n            }\n        }\n    }\n\n    /**\n     * Get all routes or only for a specific version.\n     *\n     * @param string $version\n     *\n     * @return mixed\n     */\n    public function getRoutes($version = null)\n    {\n        if (! is_null($version)) {\n            return $this->routes[$version];\n        }\n\n        return $this->routes;\n    }\n\n    /**\n     * Get a normalized iterable set of routes.\n     *\n     * @param string $version\n     *\n     * @return mixed\n     */\n    public function getIterableRoutes($version = null)\n    {\n        return $this->getRoutes($version);\n    }\n\n    /**\n     * Set the routes on the adapter.\n     *\n     * @param array $routes\n     *\n     * @return void\n     */\n    public function setRoutes(array $routes)\n    {\n        $this->routes = $routes;\n    }\n\n    /**\n     * Prepare a route for serialization.\n     *\n     * @param mixed $route\n     *\n     * @return mixed\n     */\n    public function prepareRouteForSerialization($route)\n    {\n        $route->prepareForSerialization();\n\n        return $route;\n    }\n\n    /**\n     * Gather the route middlewares.\n     *\n     * @param \\Illuminate\\Routing\\Route $route\n     *\n     * @return array\n     */\n    public function gatherRouteMiddlewares($route)\n    {\n        if (method_exists($this->router, 'gatherRouteMiddleware')) {\n            return $this->router->gatherRouteMiddleware($route);\n        }\n\n        return $this->router->gatherRouteMiddlewares($route);\n    }\n\n    /**\n     * Get the Laravel router instance.\n     *\n     * @return \\Illuminate\\Routing\\Router\n     */\n    public function getRouter()\n    {\n        return $this->router;\n    }\n\n    /**\n     * Get the global \"where\" patterns.\n     *\n     * @return array\n     */\n    public function getPatterns()\n    {\n        return $this->patterns;\n    }\n}\n"
  },
  {
    "path": "src/Routing/Adapter/Lumen.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Routing\\Adapter;\n\nuse ArrayIterator;\nuse ReflectionClass;\nuse FastRoute\\Dispatcher;\nuse FastRoute\\RouteParser;\nuse Illuminate\\Support\\Str;\nuse FastRoute\\DataGenerator;\nuse Illuminate\\Http\\Request;\nuse FastRoute\\RouteCollector;\nuse Laravel\\Lumen\\Application;\nuse Dingo\\Api\\Contract\\Routing\\Adapter;\nuse Dingo\\Api\\Exception\\UnknownVersionException;\n\nclass Lumen implements Adapter\n{\n    /**\n     * Lumen application instance.\n     *\n     * @var \\Laravel\\Lumen\\Application\n     */\n    protected $app;\n\n    /**\n     * FastRoute parser instance.\n     *\n     * @var \\FastRoute\\RouteParser\n     */\n    protected $parser;\n\n    /**\n     * FastRoute data generator instance.\n     *\n     * @var \\FastRoute\\DataGenerator\n     */\n    protected $generator;\n\n    /**\n     * FastRoute dispatcher resolver callback.\n     *\n     * @var callable\n     */\n    protected $dispatcherResolver;\n\n    /**\n     * Array of registered routes.\n     *\n     * @var array\n     */\n    protected $routes = [];\n\n    /**\n     * Array of merged old routes and API routes.\n     *\n     * @var array\n     */\n    protected $mergedRoutes = [];\n\n    /**\n     * Routes already defined on the router.\n     *\n     * @var \\Illuminate\\Routing\\RouteCollection\n     */\n    protected $oldRoutes;\n\n    /**\n     * Indicates if the middleware has been removed from the application instance.\n     *\n     * @var bool\n     */\n    protected $middlewareRemoved = false;\n\n    /**\n     * Create a new lumen adapter instance.\n     *\n     * @param \\Laravel\\Lumen\\Application $app\n     * @param \\FastRoute\\RouteParser     $parser\n     * @param \\FastRoute\\DataGenerator   $generator\n     * @param callable                   $dispatcherResolver\n     *\n     * @return void\n     */\n    public function __construct(Application $app, RouteParser $parser, DataGenerator $generator, callable $dispatcherResolver)\n    {\n        $this->app = $app;\n        $this->parser = $parser;\n        $this->generator = $generator;\n        $this->dispatcherResolver = $dispatcherResolver;\n    }\n\n    /**\n     * Dispatch a request.\n     *\n     * @param \\Illuminate\\Http\\Request $request\n     * @param string                   $version\n     *\n     * @return mixed\n     */\n    public function dispatch(Request $request, $version)\n    {\n        if (! isset($this->routes[$version])) {\n            throw new UnknownVersionException;\n        }\n\n        $this->removeMiddlewareFromApp();\n\n        $routeCollector = $this->mergeOldRoutes($version);\n        $dispatcher = call_user_func($this->dispatcherResolver, $routeCollector);\n\n        $this->app->setDispatcher($dispatcher);\n\n        $this->normalizeRequestUri($request);\n\n        return $this->app->dispatch($request);\n    }\n\n    /**\n     * Merge the old application routes with the API routes.\n     *\n     * @param string $version\n     *\n     * @return array\n     */\n    protected function mergeOldRoutes($version)\n    {\n        if (! isset($this->oldRoutes)) {\n            $this->oldRoutes = $this->app->router->getRoutes();\n        }\n        if (! isset($this->mergedRoutes[$version])) {\n            $this->mergedRoutes[$version] = $this->routes[$version];\n            foreach ($this->oldRoutes as $route) {\n                $this->mergedRoutes[$version]->addRoute($route['method'], $route['uri'], $route['action']);\n            }\n        }\n\n        return $this->mergedRoutes[$version];\n    }\n\n    /**\n     * Normalize the request URI so that Lumen can properly dispatch it.\n     *\n     * @param \\Illuminate\\Http\\Request $request\n     *\n     * @return void\n     */\n    protected function normalizeRequestUri(Request $request)\n    {\n        $query = $request->server->get('QUERY_STRING');\n\n        $uri = '/'.trim(str_replace('?'.$query, '', $request->server->get('REQUEST_URI')), '/').($query ? '?'.$query : '');\n\n        $request->server->set('REQUEST_URI', $uri);\n    }\n\n    /**\n     * Get the URI, methods, and action from the route.\n     *\n     * @param mixed                    $route\n     * @param \\Illuminate\\Http\\Request $request\n     *\n     * @return array\n     */\n    public function getRouteProperties($route, Request $request)\n    {\n        $uri = ltrim(isset($route['uri']) ? $route['uri'] : $request->getRequestUri(), '/');\n        $methods = isset($route['methods']) ? $route['methods'] : (array) $request->getMethod();\n        $action = (isset($route[1]) && is_array($route[1])) ? $route[1] : $route;\n\n        if (in_array('GET', $methods) && ! in_array('HEAD', $methods)) {\n            $methods[] = 'HEAD';\n        }\n\n        return [$uri, $methods, $action];\n    }\n\n    /**\n     * Add a route to the appropriate route collection.\n     *\n     * @param array  $methods\n     * @param array  $versions\n     * @param string $uri\n     * @param mixed  $action\n     *\n     * @return void\n     */\n    public function addRoute(array $methods, array $versions, $uri, $action)\n    {\n        $this->createRouteCollections($versions);\n\n        foreach ($versions as $version) {\n            foreach ($this->breakUriSegments($uri) as $uri) {\n                $this->routes[$version]->addRoute($methods, $uri, $action);\n            }\n        }\n    }\n\n    /**\n     * Break a URI that has optional segments into individual URIs.\n     *\n     * @param string $uri\n     *\n     * @return array\n     */\n    protected function breakUriSegments($uri)\n    {\n        if (! Str::contains($uri, '?}')) {\n            return (array) $uri;\n        }\n\n        $segments = preg_split(\n            '/\\/(\\{.*?\\})/',\n            preg_replace('/\\{(.*?)\\?\\}/', '{$1}', $uri),\n            -1,\n            PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY\n        );\n\n        $uris = [];\n\n        while ($segments) {\n            $uris[] = implode('/', $segments);\n\n            array_pop($segments);\n        }\n\n        return $uris;\n    }\n\n    /**\n     * Create the route collections for the versions.\n     *\n     * @param array $versions\n     *\n     * @return void\n     */\n    protected function createRouteCollections(array $versions)\n    {\n        foreach ($versions as $version) {\n            if (! isset($this->routes[$version])) {\n                $this->routes[$version] = new RouteCollector($this->parser, clone $this->generator);\n            }\n        }\n    }\n\n    /**\n     * Remove the global application middleware as it's run from this packages\n     * Request middleware. Lumen runs middleware later in its life cycle\n     * which results in some middleware being executed twice.\n     *\n     * @return void\n     */\n    protected function removeMiddlewareFromApp()\n    {\n        if ($this->middlewareRemoved) {\n            return;\n        }\n\n        $this->middlewareRemoved = true;\n\n        $reflection = new ReflectionClass($this->app);\n        $property = $reflection->getProperty('middleware');\n        $property->setAccessible(true);\n        $oldMiddlewares = $property->getValue($this->app);\n        $newMiddlewares = [];\n        foreach ($oldMiddlewares as $middle) {\n            if ((new ReflectionClass($middle))->hasMethod('terminate') && $middle != 'Dingo\\Api\\Http\\Middleware\\Request') {\n                $newMiddlewares = array_merge($newMiddlewares, [$middle]);\n            }\n        }\n        $property->setValue($this->app, $newMiddlewares);\n        $property->setAccessible(false);\n    }\n\n    /**\n     * Get all routes or only for a specific version.\n     *\n     * @param string $version\n     *\n     * @return mixed\n     */\n    public function getRoutes($version = null)\n    {\n        if (! is_null($version)) {\n            return $this->routes[$version];\n        }\n\n        return $this->routes;\n    }\n\n    /**\n     * Get routes in an iterable form.\n     *\n     * @param string $version\n     *\n     * @return \\ArrayIterator\n     */\n    public function getIterableRoutes($version = null)\n    {\n        $iterable = [];\n\n        foreach ($this->getRoutes($version) as $version => $collector) {\n            $routeData = $collector->getData();\n\n            // The first element in the array are the static routes that do not have any parameters.\n            foreach ($this->normalizeStaticRoutes($routeData[0]) as $method => $routes) {\n                if ($method === 'HEAD') {\n                    continue;\n                }\n\n                foreach ($routes as $route) {\n                    $route['methods'] = $this->setRouteMethods($route, $method);\n\n                    $iterable[$version][] = $route;\n                }\n            }\n\n            // The second element is the more complicated regex routes that have parameters.\n            foreach ($routeData[1] as $method => $routes) {\n                if ($method === 'HEAD') {\n                    continue;\n                }\n\n                foreach ($routes as $data) {\n                    foreach ($data['routeMap'] as [$route, $parameters]) {\n                        $route['methods'] = $this->setRouteMethods($route, $method);\n\n                        $iterable[$version][] = $route;\n                    }\n                }\n            }\n        }\n\n        return new ArrayIterator($iterable);\n    }\n\n    /**\n     * Normalize the FastRoute static routes so they're the same across multiple versions.\n     *\n     * @param array $routes\n     *\n     * @return array\n     */\n    protected function normalizeStaticRoutes(array $routes)\n    {\n        foreach (array_keys($routes) as $key) {\n            // If any of the keys are  an HTTP method then we are running on a newer version of\n            // Lumen and FastRoute which means we can leave the routes as they are.\n            if ($this->stringIsHttpMethod($key)) {\n                return $routes;\n            }\n        }\n\n        $normalized = [];\n\n        // To normalize the routes we'll take the inner array which contains the routes method as the\n        // key and make that the parent element on the array. We'll then add all routes for a\n        // particular HTTP method as children of it by keying them to their URI.\n        foreach ($routes as $uri => $value) {\n            foreach ($value as $method => $route) {\n                $normalized[$method][$uri] = $route;\n            }\n        }\n\n        return $normalized;\n    }\n\n    /**\n     * Determine if a string is an HTTP method.\n     *\n     * @param string $string\n     *\n     * @return bool\n     */\n    protected function stringIsHttpMethod($string)\n    {\n        $methods = ['GET', 'HEAD', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'];\n\n        return in_array($string, $methods, true);\n    }\n\n    /**\n     * Set the routes on the adapter.\n     *\n     * @param array $routes\n     *\n     * @return void\n     */\n    public function setRoutes(array $routes)\n    {\n        // Route caching is not implemented for Lumen.\n    }\n\n    /**\n     * Prepare a route for serialization.\n     *\n     * @param mixed $route\n     *\n     * @return mixed\n     */\n    public function prepareRouteForSerialization($route)\n    {\n        // Route caching is not implemented for Lumen.\n    }\n\n    /**\n     * Gather the route middlewares.\n     *\n     * @param array $route\n     *\n     * @return array\n     */\n    public function gatherRouteMiddlewares($route)\n    {\n        // Route middleware in Lumen is not terminated.\n        return [];\n    }\n\n    /**\n     * Append given method to the current route methods.\n     *\n     * @param array  $route\n     * @param string $method\n     *\n     * @return array\n     */\n    private function setRouteMethods($route, $method)\n    {\n        return isset($route['methods'])\n            ? array_push($route['methods'], $method)\n            : [$method];\n    }\n}\n"
  },
  {
    "path": "src/Routing/Helpers.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Routing;\n\nuse ErrorException;\nuse Dingo\\Api\\Auth\\Auth;\nuse Dingo\\Api\\Dispatcher;\nuse Dingo\\Api\\Http\\Response\\Factory;\n\n/**\n * @property \\Dingo\\Api\\Dispatcher                                            $api\n * @property \\Illuminate\\Auth\\GenericUser|\\Illuminate\\Database\\Eloquent\\Model $user\n * @property \\Dingo\\Api\\Auth\\Auth                                             $auth\n * @property \\Dingo\\Api\\Http\\Response\\Factory                                 $response\n */\ntrait Helpers\n{\n    /**\n     * Controller scopes.\n     *\n     * @var array\n     */\n    protected $scopes = [];\n\n    /**\n     * Controller authentication providers.\n     *\n     * @var array\n     */\n    protected $authenticationProviders = [];\n\n    /**\n     * Controller rate limit and expiration.\n     *\n     * @var array\n     */\n    protected $rateLimit = [];\n\n    /**\n     * Controller rate limit throttles.\n     *\n     * @var array\n     */\n    protected $throttles = [];\n\n    /**\n     * Throttles for controller methods.\n     *\n     * @param string|\\Dingo\\Api\\Contract\\Http\\RateLimit\\Throttle $class\n     * @param array                                              $options\n     *\n     * @return void\n     */\n    protected function throttle($class, array $options = [])\n    {\n        $this->throttles[] = compact('class', 'options');\n    }\n\n    /**\n     * Rate limit controller methods.\n     *\n     * @param int   $limit\n     * @param int   $expires\n     * @param array $options\n     *\n     * @return void\n     */\n    protected function rateLimit($limit, $expires, array $options = [])\n    {\n        $this->rateLimit[] = compact('limit', 'expires', 'options');\n    }\n\n    /**\n     * Add scopes to controller methods.\n     *\n     * @param string|array $scopes\n     * @param array        $options\n     *\n     * @return void\n     */\n    protected function scopes($scopes, array $options = [])\n    {\n        $scopes = $this->getPropertyValue($scopes);\n\n        $this->scopes[] = compact('scopes', 'options');\n    }\n\n    /**\n     * Authenticate with certain providers on controller methods.\n     *\n     * @param string|array $providers\n     * @param array        $options\n     *\n     * @return void\n     */\n    protected function authenticateWith($providers, array $options = [])\n    {\n        $providers = $this->getPropertyValue($providers);\n\n        $this->authenticationProviders[] = compact('providers', 'options');\n    }\n\n    /**\n     * Prepare a property value.\n     *\n     * @param string|array $value\n     *\n     * @return array\n     */\n    protected function getPropertyValue($value)\n    {\n        return is_string($value) ? explode('|', $value) : $value;\n    }\n\n    /**\n     * Get the controllers rate limiting throttles.\n     *\n     * @return array\n     */\n    public function getThrottles()\n    {\n        return $this->throttles;\n    }\n\n    /**\n     * Get the controllers rate limit and expiration.\n     *\n     * @return array\n     */\n    public function getRateLimit()\n    {\n        return $this->rateLimit;\n    }\n\n    /**\n     * Get the controllers scopes.\n     *\n     * @return array\n     */\n    public function getScopes()\n    {\n        return $this->scopes;\n    }\n\n    /**\n     * Get the controllers authentication providers.\n     *\n     * @return array\n     */\n    public function getAuthenticationProviders()\n    {\n        return $this->authenticationProviders;\n    }\n\n    /**\n     * Get the internal dispatcher instance.\n     *\n     * @return \\Dingo\\Api\\Dispatcher\n     */\n    public function api()\n    {\n        return app(Dispatcher::class);\n    }\n\n    /**\n     * Get the authenticated user.\n     *\n     * @return mixed\n     */\n    protected function user()\n    {\n        return app(Auth::class)->user();\n    }\n\n    /**\n     * Get the auth instance.\n     *\n     * @return \\Dingo\\Api\\Auth\\Auth\n     */\n    protected function auth()\n    {\n        return app(Auth::class);\n    }\n\n    /**\n     * Get the response factory instance.\n     *\n     * @return \\Dingo\\Api\\Http\\Response\\Factory\n     */\n    protected function response()\n    {\n        return app(Factory::class);\n    }\n\n    /**\n     * Magically handle calls to certain properties.\n     *\n     * @param string $key\n     *\n     * @throws \\ErrorException\n     *\n     * @return mixed\n     */\n    public function __get($key)\n    {\n        $callable = [\n            'api', 'user', 'auth', 'response',\n        ];\n\n        if (in_array($key, $callable) && method_exists($this, $key)) {\n            return $this->$key();\n        }\n\n        throw new ErrorException('Undefined property '.get_class($this).'::'.$key);\n    }\n\n    /**\n     * Magically handle calls to certain methods on the response factory.\n     *\n     * @param string $method\n     * @param array  $parameters\n     *\n     * @throws \\ErrorException\n     *\n     * @return \\Dingo\\Api\\Http\\Response\n     */\n    public function __call($method, $parameters)\n    {\n        if (method_exists($this->response(), $method) || $method == 'array') {\n            return call_user_func_array([$this->response(), $method], $parameters);\n        }\n\n        throw new ErrorException('Undefined method '.get_class($this).'::'.$method);\n    }\n}\n"
  },
  {
    "path": "src/Routing/ResourceRegistrar.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Routing;\n\nuse Illuminate\\Support\\Str;\nuse Illuminate\\Routing\\ResourceRegistrar as IlluminateResourceRegistrar;\n\nclass ResourceRegistrar extends IlluminateResourceRegistrar\n{\n    /**\n     * The default actions for a resourceful controller. Excludes 'create' and 'edit'.\n     *\n     * @var array\n     */\n    protected $resourceDefaults = ['index', 'store', 'show', 'update', 'destroy'];\n\n    /**\n     * Create a new resource registrar instance.\n     *\n     * @param \\Dingo\\Api\\Routing\\Router $router\n     *\n     * @return void\n     */\n    public function __construct(Router $router)\n    {\n        $this->router = $router;\n    }\n\n    /**\n     * Route a resource to a controller.\n     *\n     * @param  string  $name\n     * @param  string  $controller\n     * @param  array   $options\n     *\n     * @return void\n     */\n    public function register($name, $controller, array $options = [])\n    {\n        if (isset($options['parameters']) && ! isset($this->parameters)) {\n            $this->parameters = $options['parameters'];\n        }\n\n        // If the resource name contains a slash, we will assume the developer wishes to\n        // register these resource routes with a prefix so we will set that up out of\n        // the box so they don't have to mess with it. Otherwise, we will continue.\n        if (Str::contains($name, '/')) {\n            $this->prefixedResource($name, $controller, $options);\n\n            return;\n        }\n\n        // We need to extract the base resource from the resource name. Nested resources\n        // are supported in the framework, but we need to know what name to use for a\n        // place-holder on the route parameters, which should be the base resources.\n        $base = $this->getResourceWildcard(last(explode('.', $name)));\n\n        $defaults = $this->resourceDefaults;\n\n        foreach ($this->getResourceMethods($defaults, $options) as $m) {\n            $this->{'addResource'.ucfirst($m)}($name, $base, $controller, $options);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Routing/Route.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Routing;\n\nuse Illuminate\\Support\\Arr;\nuse Illuminate\\Support\\Str;\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Container\\Container;\nuse Dingo\\Api\\Contract\\Routing\\Adapter;\n\nclass Route extends \\Illuminate\\Routing\\Route\n{\n    /**\n     * Routing adapter instance.\n     *\n     * @var \\Dingo\\Api\\Contract\\Routing\\Adapter\n     */\n    protected $adapter;\n\n    /**\n     * Array of versions this route will respond to.\n     *\n     * @var array\n     */\n    protected $versions;\n\n    /**\n     * Array of scopes for OAuth 2.0 authentication.\n     *\n     * @var array\n     */\n    protected $scopes;\n\n    /**\n     * Array of authentication providers.\n     *\n     * @var array\n     */\n    protected $authenticationProviders;\n\n    /**\n     * The rate limit for this route.\n     *\n     * @var int\n     */\n    protected $rateLimit;\n\n    /**\n     * The expiration time for any rate limit set on this rate.\n     *\n     * @var int\n     */\n    protected $rateExpiration;\n\n    /**\n     * The throttle used by the route, takes precedence over rate limits.\n     *\n     * @return string|\\Dingo\\Api\\Contract\\Http\\RateLimit\\Throttle\n     */\n    protected $throttle;\n\n    /**\n     * Controller class name.\n     *\n     * @var string\n     */\n    protected $controllerClass;\n\n    /**\n     * Indicates if the request is conditional.\n     *\n     * @var bool\n     */\n    protected $conditionalRequest = true;\n\n    /**\n     * Middleware applied to route.\n     *\n     * @var array\n     */\n    protected $middleware;\n    private $route;\n\n    /**\n     * Create a new route instance.\n     *\n     * @param \\Dingo\\Api\\Contract\\Routing\\Adapter $adapter\n     * @param \\Illuminate\\Container\\Container     $container\n     * @param \\Illuminate\\Http\\Request            $request\n     * @param array|\\Illuminate\\Routing\\Route     $route\n     */\n    public function __construct(Adapter $adapter, Container $container, Request $request, $route)\n    {\n        $this->adapter = $adapter;\n        $this->container = $container;\n        $this->route = $route;\n\n        $this->setupRouteProperties($request, $route);\n\n        parent::__construct($this->methods, $this->uri, $this->action);\n    }\n\n    /**\n     * Setup the route properties.\n     *\n     * @param Request $request\n     * @param         $route\n     *\n     * @return void\n     */\n    protected function setupRouteProperties(Request $request, $route)\n    {\n        [$this->uri, $this->methods, $this->action] = $this->adapter->getRouteProperties($route, $request);\n\n        $this->versions = Arr::pull($this->action, 'version');\n        $this->conditionalRequest = Arr::pull($this->action, 'conditionalRequest', true);\n        $this->middleware = (array) Arr::pull($this->action, 'middleware', []);\n        $this->throttle = Arr::pull($this->action, 'throttle');\n        $this->scopes = Arr::pull($this->action, 'scopes', []);\n        $this->authenticationProviders = Arr::pull($this->action, 'providers', []);\n        $this->rateLimit = Arr::pull($this->action, 'limit', 0);\n        $this->rateExpiration = Arr::pull($this->action, 'expires', 0);\n\n        // Now that the default route properties have been set we'll go ahead and merge\n        // any controller properties to fully configure the route.\n        $this->mergeControllerProperties();\n\n        // If we have a string based throttle then we'll new up an instance of the\n        // throttle through the container.\n        if (is_string($this->throttle)) {\n            $this->throttle = $this->container->make($this->throttle);\n        }\n    }\n\n    /**\n     * Merge the controller properties onto the route properties.\n     */\n    protected function mergeControllerProperties()\n    {\n        if (isset($this->action['uses']) && is_string($this->action['uses']) && Str::contains($this->action['uses'],\n                '@')) {\n            $this->action['controller'] = $this->action['uses'];\n\n            $this->makeControllerInstance();\n        }\n\n        if (! $this->controllerUsesHelpersTrait()) {\n            return;\n        }\n\n        $controller = $this->getControllerInstance();\n\n        $controllerMiddleware = [];\n\n        if (method_exists($controller, 'getMiddleware')) {\n            $controllerMiddleware = $controller->getMiddleware();\n        } elseif (method_exists($controller, 'getMiddlewareForMethod')) {\n            $controllerMiddleware = $controller->getMiddlewareForMethod($this->controllerMethod);\n        }\n\n        $this->middleware = array_merge($this->middleware, $controllerMiddleware);\n\n        if ($property = $this->findControllerPropertyOptions('throttles')) {\n            $this->throttle = $property['class'];\n        }\n\n        if ($property = $this->findControllerPropertyOptions('scopes')) {\n            $this->scopes = array_merge($this->scopes, $property['scopes']);\n        }\n\n        if ($property = $this->findControllerPropertyOptions('authenticationProviders')) {\n            $this->authenticationProviders = array_merge($this->authenticationProviders, $property['providers']);\n        }\n\n        if ($property = $this->findControllerPropertyOptions('rateLimit')) {\n            $this->rateLimit = $property['limit'];\n            $this->rateExpiration = $property['expires'];\n        }\n    }\n\n    /**\n     * Find the controller options and whether or not it will apply to this routes controller method.\n     *\n     * @param string $name\n     *\n     * @return array\n     */\n    protected function findControllerPropertyOptions($name)\n    {\n        $properties = [];\n\n        foreach ($this->getControllerInstance()->{'get'.ucfirst($name)}() as $property) {\n            if (isset($property['options']) && ! $this->optionsApplyToControllerMethod($property['options'])) {\n                continue;\n            }\n\n            unset($property['options']);\n\n            $properties = array_merge_recursive($properties, $property);\n        }\n\n        return $properties;\n    }\n\n    /**\n     * Determine if a controller method is in an array of options.\n     *\n     * @param array $options\n     *\n     * @return bool\n     */\n    protected function optionsApplyToControllerMethod(array $options)\n    {\n        if (empty($options)) {\n            return true;\n        } elseif (isset($options['only']) && in_array($this->controllerMethod,\n                $this->explodeOnPipes($options['only']))) {\n            return true;\n        } elseif (isset($options['except'])) {\n            return ! in_array($this->controllerMethod, $this->explodeOnPipes($options['except']));\n        } elseif (in_array($this->controllerMethod, $this->explodeOnPipes($options))) {\n            return true;\n        }\n\n        return false;\n    }\n\n    /**\n     * Explode a value on a pipe delimiter.\n     *\n     * @param string|array $value\n     *\n     * @return array\n     */\n    protected function explodeOnPipes($value)\n    {\n        return is_string($value) ? explode('|', $value) : $value;\n    }\n\n    /**\n     * Determine if the controller instance uses the helpers trait.\n     *\n     * @return bool\n     */\n    protected function controllerUsesHelpersTrait()\n    {\n        if (! $controller = $this->getControllerInstance()) {\n            return false;\n        }\n\n        $traits = [];\n\n        do {\n            $traits = array_merge(class_uses($controller, false), $traits);\n        } while ($controller = get_parent_class($controller));\n\n        foreach ($traits as $trait => $same) {\n            $traits = array_merge(class_uses($trait, false), $traits);\n        }\n\n        return isset($traits[Helpers::class]);\n    }\n\n    /**\n     * Get the routes controller instance.\n     *\n     * @return null|\\Illuminate\\Routing\\Controller|\\Laravel\\Lumen\\Routing\\Controller\n     */\n    public function getControllerInstance()\n    {\n        return $this->controller;\n    }\n\n    /**\n     * Make a new controller instance through the container.\n     *\n     * @return \\Illuminate\\Routing\\Controller|\\Laravel\\Lumen\\Routing\\Controller\n     */\n    protected function makeControllerInstance()\n    {\n        [$this->controllerClass, $this->controllerMethod] = explode('@', $this->action['uses']);\n\n        $this->container->instance($this->controllerClass,\n            $this->controller = $this->container->make($this->controllerClass));\n\n        return $this->controller;\n    }\n\n    /**\n     * Determine if the route is protected.\n     *\n     * @return bool\n     */\n    public function isProtected()\n    {\n        if (isset($this->middleware['api.auth']) || in_array('api.auth', $this->middleware)) {\n            if ($this->controller && isset($this->middleware['api.auth'])) {\n                return $this->optionsApplyToControllerMethod($this->middleware['api.auth']);\n            }\n\n            return true;\n        }\n\n        return false;\n    }\n\n    /**\n     * Determine if the route has a throttle.\n     *\n     * @return bool\n     */\n    public function hasThrottle()\n    {\n        return ! is_null($this->throttle);\n    }\n\n    /**\n     * Get the route throttle.\n     *\n     * @return string|\\Dingo\\Api\\Http\\RateLimit\\Throttle\\Throttle\n     */\n    public function throttle()\n    {\n        return $this->throttle;\n    }\n\n    /**\n     * Get the route throttle.\n     *\n     * @return string|\\Dingo\\Api\\Http\\RateLimit\\Throttle\\Throttle\n     */\n    public function getThrottle()\n    {\n        return $this->throttle;\n    }\n\n    /**\n     * Get the route scopes.\n     *\n     * @return array\n     */\n    public function scopes()\n    {\n        return $this->scopes;\n    }\n\n    /**\n     * Get the route scopes.\n     *\n     * @return array\n     */\n    public function getScopes()\n    {\n        return $this->scopes;\n    }\n\n    /**\n     * Check if route requires all scopes or any scope to be valid.\n     *\n     * @return bool\n     */\n    public function scopeStrict()\n    {\n        return Arr::get($this->action, 'scopeStrict', false);\n    }\n\n    /**\n     * Get the route authentication providers.\n     *\n     * @return array\n     */\n    public function authenticationProviders()\n    {\n        return $this->authenticationProviders;\n    }\n\n    /**\n     * Get the route authentication providers.\n     *\n     * @return array\n     */\n    public function getAuthenticationProviders()\n    {\n        return $this->authenticationProviders;\n    }\n\n    /**\n     * Get the rate limit for this route.\n     *\n     * @return int\n     */\n    public function rateLimit()\n    {\n        return $this->rateLimit;\n    }\n\n    /**\n     * Get the rate limit for this route.\n     *\n     * @return int\n     */\n    public function getRateLimit()\n    {\n        return $this->rateLimit;\n    }\n\n    /**\n     * Get the rate limit expiration time for this route.\n     *\n     * @return int\n     */\n    public function rateLimitExpiration()\n    {\n        return $this->rateExpiration;\n    }\n\n    /**\n     * Get the rate limit expiration time for this route.\n     *\n     * @return int\n     */\n    public function getRateLimitExpiration()\n    {\n        return $this->rateExpiration;\n    }\n\n    /**\n     * Get the name of the route.\n     *\n     * @return string\n     */\n    public function getName()\n    {\n        return Arr::get($this->action, 'as', null);\n    }\n\n    /**\n     * Determine if the request is conditional.\n     *\n     * @return bool\n     */\n    public function requestIsConditional()\n    {\n        return $this->conditionalRequest === true;\n    }\n\n    /**\n     * Get the versions for the route.\n     *\n     * @return array\n     */\n    public function getVersions()\n    {\n        return $this->versions;\n    }\n\n    /**\n     * Get the versions for the route.\n     *\n     * @return array\n     */\n    public function versions()\n    {\n        return $this->getVersions();\n    }\n\n    /**\n     * Get the URI associated with the route.\n     *\n     * @return string\n     */\n    public function getPath()\n    {\n        return $this->uri();\n    }\n\n    /**\n     * Get the URI associated with the route.\n     *\n     * @return string\n     */\n    public function uri()\n    {\n        return $this->uri;\n    }\n\n    /**\n     * Get the HTTP verbs the route responds to.\n     *\n     * @return array\n     */\n    public function getMethods()\n    {\n        return $this->methods();\n    }\n\n    /**\n     * Get the HTTP verbs the route responds to.\n     *\n     * @return array\n     */\n    public function methods()\n    {\n        return $this->methods;\n    }\n\n    /**\n     * Determine if the route only responds to HTTP requests.\n     *\n     * @return bool\n     */\n    public function httpOnly()\n    {\n        return in_array('http', $this->action, true)\n            || (array_key_exists('http', $this->action) && $this->action['http']);\n    }\n\n    /**\n     * Determine if the route only responds to HTTPS requests.\n     *\n     * @return bool\n     */\n    public function httpsOnly()\n    {\n        return $this->secure();\n    }\n\n    /**\n     * Determine if the route only responds to HTTPS requests.\n     *\n     * @return bool\n     */\n    public function secure()\n    {\n        return in_array('https', $this->action, true)\n            || (array_key_exists('https', $this->action) && $this->action['https']);\n    }\n\n    /**\n     * Return the middlewares for this route.\n     *\n     * @return array\n     */\n    public function getMiddleware()\n    {\n        return $this->middleware;\n    }\n}\n"
  },
  {
    "path": "src/Routing/RouteCollection.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Routing;\n\nuse Countable;\nuse ArrayIterator;\nuse IteratorAggregate;\n\nclass RouteCollection implements Countable, IteratorAggregate\n{\n    /**\n     * Routes on the collection.\n     *\n     * @var array\n     */\n    protected $routes = [];\n\n    /**\n     * Lookup for named routes.\n     *\n     * @var array\n     */\n    protected $names = [];\n\n    /**\n     * Lookup for action routes.\n     *\n     * @var array\n     */\n    protected $actions = [];\n\n    /**\n     * Add a route to the collection.\n     *\n     * @param \\Dingo\\Api\\Routing\\Route $route\n     *\n     * @return \\Dingo\\Api\\Routing\\Route\n     */\n    public function add(Route $route)\n    {\n        $this->routes[] = $route;\n\n        $this->addLookups($route);\n\n        return $route;\n    }\n\n    /**\n     * Add route lookups.\n     *\n     * @param \\Dingo\\Api\\Routing\\Route $route\n     *\n     * @return void\n     */\n    protected function addLookups(Route $route)\n    {\n        $action = $route->getAction();\n\n        if (isset($action['as'])) {\n            $this->names[$action['as']] = $route;\n        }\n\n        if (isset($action['controller'])) {\n            $this->actions[$action['controller']] = $route;\n        }\n    }\n\n    /**\n     * Get a route by name.\n     *\n     * @param string $name\n     *\n     * @return \\Dingo\\Api\\Routing\\Route|null\n     */\n    public function getByName($name)\n    {\n        return isset($this->names[$name]) ? $this->names[$name] : null;\n    }\n\n    /**\n     * Get a route by action.\n     *\n     * @param string $action\n     *\n     * @return \\Dingo\\Api\\Routing\\Route|null\n     */\n    public function getByAction($action)\n    {\n        return isset($this->actions[$action]) ? $this->actions[$action] : null;\n    }\n\n    /**\n     * Get all routes.\n     *\n     * @return array\n     */\n    public function getRoutes()\n    {\n        return $this->routes;\n    }\n\n    /**\n     * Get an iterator for the items.\n     *\n     * @return \\ArrayIterator\n     */\n    public function getIterator()\n    {\n        return new ArrayIterator($this->getRoutes());\n    }\n\n    /**\n     * Count the number of items in the collection.\n     *\n     * @return int\n     */\n    public function count()\n    {\n        return count($this->getRoutes());\n    }\n}\n"
  },
  {
    "path": "src/Routing/Router.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Routing;\n\nuse Closure;\nuse Dingo\\Api\\Contract\\Debug\\ExceptionHandler;\nuse Dingo\\Api\\Contract\\Routing\\Adapter;\nuse Dingo\\Api\\Http\\InternalRequest;\nuse Dingo\\Api\\Http\\Request;\nuse Dingo\\Api\\Http\\Response;\nuse Exception;\nuse Illuminate\\Container\\Container;\nuse Illuminate\\Http\\JsonResponse;\nuse Illuminate\\Http\\Response as IlluminateResponse;\nuse Illuminate\\Support\\Arr;\nuse Illuminate\\Support\\Str;\nuse RuntimeException;\nuse Symfony\\Component\\HttpKernel\\Exception\\NotAcceptableHttpException;\n\nclass Router\n{\n    /**\n     * Routing adapter instance.\n     *\n     * @var \\Dingo\\Api\\Contract\\Routing\\Adapter\n     */\n    protected $adapter;\n\n    /**\n     * Accept parser instance.\n     *\n     * @var \\Dingo\\Api\\Http\\Parser\\Accept\n     */\n    protected $accept;\n\n    /**\n     * Exception handler instance.\n     *\n     * @var \\Dingo\\Api\\Contract\\Debug\\ExceptionHandler\n     */\n    protected $exception;\n\n    /**\n     * Application container instance.\n     *\n     * @var \\Illuminate\\Container\\Container\n     */\n    protected $container;\n\n    /**\n     * Group stack array.\n     *\n     * @var array\n     */\n    protected $groupStack = [];\n\n    /**\n     * Indicates if the request is conditional.\n     *\n     * @var bool\n     */\n    protected $conditionalRequest = true;\n\n    /**\n     * The current route being dispatched.\n     *\n     * @var \\Dingo\\Api\\Routing\\Route\n     */\n    protected $currentRoute;\n\n    /**\n     * The number of routes dispatched.\n     *\n     * @var int\n     */\n    protected $routesDispatched = 0;\n\n    /**\n     * The API domain.\n     *\n     * @var string\n     */\n    protected $domain;\n\n    /**\n     * The API prefix.\n     *\n     * @var string\n     */\n    protected $prefix;\n\n    /**\n     * Create a new router instance.\n     *\n     * @param \\Dingo\\Api\\Contract\\Routing\\Adapter        $adapter\n     * @param \\Dingo\\Api\\Contract\\Debug\\ExceptionHandler $exception\n     * @param \\Illuminate\\Container\\Container            $container\n     * @param string                                     $domain\n     * @param string                                     $prefix\n     *\n     * @return void\n     */\n    public function __construct(Adapter $adapter, ExceptionHandler $exception, Container $container, $domain, $prefix)\n    {\n        $this->adapter = $adapter;\n        $this->exception = $exception;\n        $this->container = $container;\n        $this->domain = $domain;\n        $this->prefix = $prefix;\n    }\n\n    /**\n     * An alias for calling the group method, allows a more fluent API\n     * for registering a new API version group with optional\n     * attributes and a required callback.\n     *\n     * This method can be called without the third parameter, however,\n     * the callback should always be the last parameter.\n     *\n     * @param array|string   $version\n     * @param array|callable $second\n     * @param callable       $third\n     *\n     * @return void\n     */\n    public function version($version, $second, $third = null)\n    {\n        if (func_num_args() == 2) {\n            [$version, $callback, $attributes] = array_merge(func_get_args(), [[]]);\n        } else {\n            [$version, $attributes, $callback] = func_get_args();\n        }\n\n        $attributes = array_merge($attributes, ['version' => $version]);\n\n        $this->group($attributes, $callback);\n    }\n\n    /**\n     * Create a new route group.\n     *\n     * @param array    $attributes\n     * @param callable $callback\n     *\n     * @return void\n     */\n    public function group(array $attributes, $callback)\n    {\n        if (! isset($attributes['conditionalRequest'])) {\n            $attributes['conditionalRequest'] = $this->conditionalRequest;\n        }\n\n        $attributes = $this->mergeLastGroupAttributes($attributes);\n\n        if (! isset($attributes['version'])) {\n            throw new RuntimeException('A version is required for an API group definition.');\n        } else {\n            $attributes['version'] = (array) $attributes['version'];\n        }\n\n        if ((! isset($attributes['prefix']) || empty($attributes['prefix'])) && isset($this->prefix)) {\n            $attributes['prefix'] = $this->prefix;\n        }\n\n        if ((! isset($attributes['domain']) || empty($attributes['domain'])) && isset($this->domain)) {\n            $attributes['domain'] = $this->domain;\n        }\n\n        $this->groupStack[] = $attributes;\n\n        call_user_func($callback, $this);\n\n        array_pop($this->groupStack);\n    }\n\n    /**\n     * Create a new GET route.\n     *\n     * @param string                $uri\n     * @param array|string|callable $action\n     *\n     * @return mixed\n     */\n    public function get($uri, $action)\n    {\n        return $this->addRoute(['GET', 'HEAD'], $uri, $action);\n    }\n\n    /**\n     * Create a new POST route.\n     *\n     * @param string                $uri\n     * @param array|string|callable $action\n     *\n     * @return mixed\n     */\n    public function post($uri, $action)\n    {\n        return $this->addRoute('POST', $uri, $action);\n    }\n\n    /**\n     * Create a new PUT route.\n     *\n     * @param string                $uri\n     * @param array|string|callable $action\n     *\n     * @return mixed\n     */\n    public function put($uri, $action)\n    {\n        return $this->addRoute('PUT', $uri, $action);\n    }\n\n    /**\n     * Create a new PATCH route.\n     *\n     * @param string                $uri\n     * @param array|string|callable $action\n     *\n     * @return mixed\n     */\n    public function patch($uri, $action)\n    {\n        return $this->addRoute('PATCH', $uri, $action);\n    }\n\n    /**\n     * Create a new DELETE route.\n     *\n     * @param string                $uri\n     * @param array|string|callable $action\n     *\n     * @return mixed\n     */\n    public function delete($uri, $action)\n    {\n        return $this->addRoute('DELETE', $uri, $action);\n    }\n\n    /**\n     * Create a new OPTIONS route.\n     *\n     * @param string                $uri\n     * @param array|string|callable $action\n     *\n     * @return mixed\n     */\n    public function options($uri, $action)\n    {\n        return $this->addRoute('OPTIONS', $uri, $action);\n    }\n\n    /**\n     * Create a new route that responding to all verbs.\n     *\n     * @param string                $uri\n     * @param array|string|callable $action\n     *\n     * @return mixed\n     */\n    public function any($uri, $action)\n    {\n        $verbs = ['GET', 'HEAD', 'POST', 'PUT', 'PATCH', 'DELETE'];\n\n        return $this->addRoute($verbs, $uri, $action);\n    }\n\n    /**\n     * Create a new route with the given verbs.\n     *\n     * @param array|string          $methods\n     * @param string                $uri\n     * @param array|string|callable $action\n     *\n     * @return mixed\n     */\n    public function match($methods, $uri, $action)\n    {\n        return $this->addRoute(array_map('strtoupper', (array) $methods), $uri, $action);\n    }\n\n    /**\n     * Register an array of resources.\n     *\n     * @param array $resources\n     *\n     * @return void\n     */\n    public function resources(array $resources)\n    {\n        foreach ($resources as $name => $resource) {\n            $options = [];\n\n            if (is_array($resource)) {\n                [$resource, $options] = $resource;\n            }\n\n            $this->resource($name, $resource, $options);\n        }\n    }\n\n    /**\n     * Register a resource controller.\n     *\n     * @param string $name\n     * @param string $controller\n     * @param array  $options\n     *\n     * @return void\n     */\n    public function resource($name, $controller, array $options = [])\n    {\n        if ($this->container->bound(ResourceRegistrar::class)) {\n            $registrar = $this->container->make(ResourceRegistrar::class);\n        } else {\n            $registrar = new ResourceRegistrar($this);\n        }\n\n        $registrar->register($name, $controller, $options);\n    }\n\n    /**\n     * Add a route to the routing adapter.\n     *\n     * @param string|array          $methods\n     * @param string                $uri\n     * @param string|array|callable $action\n     *\n     * @return mixed\n     */\n    public function addRoute($methods, $uri, $action)\n    {\n        if (is_string($action)) {\n            $action = ['uses' => $action, 'controller' => $action];\n        } elseif ($action instanceof Closure) {\n            $action = [$action];\n        } elseif (is_array($action)) {\n            // For this sort of syntax $api->post('login', [LoginController::class, 'login']);\n            if (is_string(Arr::first($action)) && class_exists(Arr::first($action)) && count($action) == 2) {\n                $action = implode('@', $action);\n                $action = ['uses' => $action, 'controller' => $action];\n            }\n        }\n\n        $action = $this->mergeLastGroupAttributes($action);\n\n        $action = $this->addControllerMiddlewareToRouteAction($action);\n\n        $uri = $uri === '/' ? $uri : '/'.trim($uri, '/');\n\n        if (! empty($action['prefix'])) {\n            $uri = '/'.ltrim(rtrim(trim($action['prefix'], '/').'/'.trim($uri, '/'), '/'), '/');\n\n            unset($action['prefix']);\n        }\n\n        $action['uri'] = $uri;\n\n        return $this->adapter->addRoute((array) $methods, $action['version'], $uri, $action);\n    }\n\n    /**\n     * Add the controller preparation middleware to the beginning of the routes middleware.\n     *\n     * @param array $action\n     *\n     * @return array\n     */\n    protected function addControllerMiddlewareToRouteAction(array $action)\n    {\n        array_unshift($action['middleware'], 'api.controllers');\n\n        return $action;\n    }\n\n    /**\n     * Merge the last groups attributes.\n     *\n     * @param array $attributes\n     *\n     * @return array\n     */\n    protected function mergeLastGroupAttributes(array $attributes)\n    {\n        if (empty($this->groupStack)) {\n            return $this->mergeGroup($attributes, []);\n        }\n\n        return $this->mergeGroup($attributes, end($this->groupStack));\n    }\n\n    /**\n     * Merge the given group attributes.\n     *\n     * @param array $new\n     * @param array $old\n     *\n     * @return array\n     */\n    protected function mergeGroup(array $new, array $old)\n    {\n        $new['namespace'] = $this->formatNamespace($new, $old);\n\n        $new['prefix'] = $this->formatPrefix($new, $old);\n\n        foreach (['middleware', 'providers', 'scopes', 'before', 'after'] as $option) {\n            $new[$option] = $this->formatArrayBasedOption($option, $new);\n        }\n\n        if (isset($new['domain'])) {\n            unset($old['domain']);\n        }\n\n        if (isset($new['conditionalRequest'])) {\n            unset($old['conditionalRequest']);\n        }\n\n        if (isset($new['uses'])) {\n            $new['uses'] = $this->formatUses($new, $old);\n        }\n\n        $new['where'] = array_merge(Arr::get($old, 'where', []), Arr::get($new, 'where', []));\n\n        if (isset($old['as'])) {\n            $new['as'] = trim($old['as'].'.'.Arr::get($new, 'as', ''), '.');\n        }\n\n        return array_merge_recursive(Arr::except($old, ['namespace', 'prefix', 'where', 'as']), $new);\n    }\n\n    /**\n     * Format an array based option in a route action.\n     *\n     * @param string $option\n     * @param array  $new\n     *\n     * @return array\n     */\n    protected function formatArrayBasedOption($option, array $new)\n    {\n        $value = Arr::get($new, $option, []);\n\n        return is_string($value) ? explode('|', $value) : $value;\n    }\n\n    /**\n     * Format the uses key in a route action.\n     *\n     * @param array $new\n     * @param array $old\n     *\n     * @return string\n     */\n    protected function formatUses(array $new, array $old)\n    {\n        if (isset($old['namespace']) && is_string($new['uses']) && strpos($new['uses'], '\\\\') !== 0) {\n            return $old['namespace'].'\\\\'.$new['uses'];\n        }\n\n        return $new['uses'];\n    }\n\n    /**\n     * Format the namespace for the new group attributes.\n     *\n     * @param array $new\n     * @param array $old\n     *\n     * @return string\n     */\n    protected function formatNamespace(array $new, array $old)\n    {\n        if (isset($new['namespace']) && isset($old['namespace'])) {\n            return trim($old['namespace'], '\\\\').'\\\\'.trim($new['namespace'], '\\\\');\n        } elseif (isset($new['namespace'])) {\n            return trim($new['namespace'], '\\\\');\n        }\n\n        return Arr::get($old, 'namespace');\n    }\n\n    /**\n     * Format the prefix for the new group attributes.\n     *\n     * @param array $new\n     * @param array $old\n     *\n     * @return string\n     */\n    protected function formatPrefix($new, $old)\n    {\n        if (isset($new['prefix'])) {\n            return trim(Arr::get($old, 'prefix'), '/').'/'.trim($new['prefix'], '/');\n        }\n\n        return Arr::get($old, 'prefix', '');\n    }\n\n    /**\n     * Dispatch a request via the adapter.\n     *\n     * @param \\Dingo\\Api\\Http\\Request $request\n     *\n     * @throws \\Exception\n     *\n     * @return \\Dingo\\Api\\Http\\Response\n     */\n    public function dispatch(Request $request)\n    {\n        $this->currentRoute = null;\n\n        $this->container->instance(Request::class, $request);\n\n        $this->routesDispatched++;\n\n        try {\n            $response = $this->adapter->dispatch($request, $request->version());\n        } catch (Exception $exception) {\n            if ($request instanceof InternalRequest) {\n                throw $exception;\n            }\n\n            $this->exception->report($exception);\n\n            $response = $this->exception->handle($exception);\n        }\n\n        return $this->prepareResponse($response, $request, $request->format());\n    }\n\n    /**\n     * Prepare a response by transforming and formatting it correctly.\n     *\n     * @param mixed                   $response\n     * @param \\Dingo\\Api\\Http\\Request $request\n     * @param string                  $format\n     *\n     * @return \\Dingo\\Api\\Http\\Response\n     */\n    protected function prepareResponse($response, Request $request, $format)\n    {\n        if ($response instanceof IlluminateResponse) {\n            $response = Response::makeFromExisting($response);\n        } elseif ($response instanceof JsonResponse) {\n            $response = Response::makeFromJson($response);\n        }\n\n        if ($response instanceof Response) {\n            // If we try and get a formatter that does not exist we'll let the exception\n            // handler deal with it. At worst we'll get a generic JSON response that\n            // a consumer can hopefully deal with. Ideally they won't be using\n            // an unsupported format.\n            try {\n                $response->getFormatter($format)->setResponse($response)->setRequest($request);\n            } catch (NotAcceptableHttpException $exception) {\n                return $this->exception->handle($exception);\n            }\n\n            $response = $response->morph($format);\n        }\n\n        if ($response->isSuccessful() && $this->requestIsConditional()) {\n            if (! $response->headers->has('ETag')) {\n                $response->setEtag(sha1($response->getContent() ?: ''));\n            }\n\n            $response->isNotModified($request);\n        }\n\n        return $response;\n    }\n\n    /**\n     * Gather the middleware for the given route.\n     *\n     * @param mixed $route\n     *\n     * @return array\n     */\n    public function gatherRouteMiddlewares($route)\n    {\n        return $this->adapter->gatherRouteMiddlewares($route);\n    }\n\n    /**\n     * Determine if the request is conditional.\n     *\n     * @return bool\n     */\n    protected function requestIsConditional()\n    {\n        return $this->getCurrentRoute()->requestIsConditional();\n    }\n\n    /**\n     * Set the conditional request.\n     *\n     * @param bool $conditionalRequest\n     *\n     * @return void\n     */\n    public function setConditionalRequest($conditionalRequest)\n    {\n        $this->conditionalRequest = $conditionalRequest;\n    }\n\n    /**\n     * Get the current request instance.\n     *\n     * @return \\Dingo\\Api\\Http\\Request\n     */\n    public function getCurrentRequest()\n    {\n        return $this->container['request'];\n    }\n\n    /**\n     * Get the current route instance.\n     *\n     * @return \\Dingo\\Api\\Routing\\Route\n     */\n    public function getCurrentRoute()\n    {\n        if (isset($this->currentRoute)) {\n            return $this->currentRoute;\n        } elseif (! $this->hasDispatchedRoutes() || ! $route = $this->container['request']->route()) {\n            return;\n        }\n\n        return $this->currentRoute = $this->createRoute($route);\n    }\n\n    /**\n     * Get the currently dispatched route instance.\n     *\n     * @return \\Illuminate\\Routing\\Route\n     */\n    public function current()\n    {\n        return $this->getCurrentRoute();\n    }\n\n    /**\n     * Create a new route instance from an adapter route.\n     *\n     * @param array|\\Illuminate\\Routing\\Route $route\n     *\n     * @return \\Dingo\\Api\\Routing\\Route\n     */\n    public function createRoute($route)\n    {\n        return new Route($this->adapter, $this->container, $this->container['request'], $route);\n    }\n\n    /**\n     * Set the current route instance.\n     *\n     * @param \\Dingo\\Api\\Routing\\Route $route\n     *\n     * @return void\n     */\n    public function setCurrentRoute(Route $route)\n    {\n        $this->currentRoute = $route;\n    }\n\n    /**\n     * Determine if the router has a group stack.\n     *\n     * @return bool\n     */\n    public function hasGroupStack()\n    {\n        return ! empty($this->groupStack);\n    }\n\n    /**\n     * Get the prefix from the last group on the stack.\n     *\n     * @return string\n     */\n    public function getLastGroupPrefix()\n    {\n        if (empty($this->groupStack)) {\n            return '';\n        }\n\n        $group = end($this->groupStack);\n\n        return $group['prefix'];\n    }\n\n    /**\n     * Get all routes registered on the adapter.\n     *\n     * @param string $version\n     *\n     * @return mixed\n     */\n    public function getRoutes($version = null)\n    {\n        $routes = $this->adapter->getIterableRoutes($version);\n\n        if (! is_null($version)) {\n            $routes = [$version => $routes];\n        }\n\n        $collections = [];\n\n        foreach ($routes as $key => $value) {\n            $collections[$key] = new RouteCollection($this->container['request']);\n\n            foreach ($value as $route) {\n                $route = $this->createRoute($route);\n\n                $collections[$key]->add($route);\n            }\n        }\n\n        return is_null($version) ? $collections : $collections[$version];\n    }\n\n    /**\n     * Get the raw adapter routes.\n     *\n     * @return array\n     */\n    public function getAdapterRoutes()\n    {\n        return $this->adapter->getRoutes();\n    }\n\n    /**\n     * Set the raw adapter routes.\n     *\n     * @param array $routes\n     *\n     * @return void\n     */\n    public function setAdapterRoutes(array $routes)\n    {\n        $this->adapter->setRoutes($routes);\n\n        $this->container->instance('api.routes', $this->getRoutes());\n    }\n\n    /**\n     * Get the number of routes dispatched.\n     *\n     * @return int\n     */\n    public function getRoutesDispatched()\n    {\n        return $this->routesDispatched;\n    }\n\n    /**\n     * Determine if the router has dispatched any routes.\n     *\n     * @return bool\n     */\n    public function hasDispatchedRoutes()\n    {\n        return $this->routesDispatched > 0;\n    }\n\n    /**\n     * Get the current route name.\n     *\n     * @return string|null\n     */\n    public function currentRouteName()\n    {\n        return $this->current() ? $this->current()->getName() : null;\n    }\n\n    /**\n     * Alias for the \"currentRouteNamed\" method.\n     *\n     * @param mixed string\n     *\n     * @return bool\n     */\n    public function is()\n    {\n        foreach (func_get_args() as $pattern) {\n            if (Str::is($pattern, $this->currentRouteName())) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    /**\n     * Determine if the current route matches a given name.\n     *\n     * @param string $name\n     *\n     * @return bool\n     */\n    public function currentRouteNamed($name)\n    {\n        return $this->current() ? $this->current()->getName() == $name : false;\n    }\n\n    /**\n     * Get the current route action.\n     *\n     * @return string|null\n     */\n    public function currentRouteAction()\n    {\n        if (! $route = $this->current()) {\n            return;\n        }\n\n        $action = $route->getAction();\n\n        return is_string($action['uses']) ? $action['uses'] : null;\n    }\n\n    /**\n     * Alias for the \"currentRouteUses\" method.\n     *\n     * @param  mixed  string\n     *\n     * @return bool\n     */\n    public function uses()\n    {\n        foreach (func_get_args() as $pattern) {\n            if (Str::is($pattern, $this->currentRouteAction())) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    /**\n     * Determine if the current route action matches a given action.\n     *\n     * @param string $action\n     *\n     * @return bool\n     */\n    public function currentRouteUses($action)\n    {\n        return $this->currentRouteAction() == $action;\n    }\n\n    /**\n     * Flush the router's middleware groups.\n     *\n     * @return $this\n     */\n    public function flushMiddlewareGroups()\n    {\n        return $this;\n    }\n}\n"
  },
  {
    "path": "src/Routing/UrlGenerator.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Routing;\n\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Routing\\UrlGenerator as IlluminateUrlGenerator;\n\nclass UrlGenerator extends IlluminateUrlGenerator\n{\n    /**\n     * Array of route collections.\n     *\n     * @var array\n     */\n    protected $collections;\n\n    /**\n     * Create a new URL generator instance.\n     *\n     * @param \\Dingo\\Api\\Http\\Request $request\n     *\n     * @return void\n     */\n    public function __construct(Request $request)\n    {\n        $this->setRequest($request);\n    }\n\n    /**\n     * Set the routes to use from the version.\n     *\n     * @param string $version\n     *\n     * @return \\Dingo\\Api\\Routing\\UrlGenerator\n     */\n    public function version($version)\n    {\n        $this->routes = $this->collections[$version];\n\n        return $this;\n    }\n\n    /**\n     * Set the route collection instance.\n     *\n     * @param array $collections\n     */\n    public function setRouteCollections(array $collections)\n    {\n        $this->collections = $collections;\n    }\n}\n"
  },
  {
    "path": "src/Transformer/Adapter/Fractal.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Transformer\\Adapter;\n\nuse Dingo\\Api\\Http\\Request;\nuse Dingo\\Api\\Transformer\\Binding;\nuse League\\Fractal\\TransformerAbstract;\nuse Dingo\\Api\\Contract\\Transformer\\Adapter;\nuse League\\Fractal\\Manager as FractalManager;\nuse League\\Fractal\\Resource\\Item as FractalItem;\nuse League\\Fractal\\Pagination\\IlluminatePaginatorAdapter;\nuse Illuminate\\Support\\Collection as IlluminateCollection;\nuse League\\Fractal\\Resource\\Collection as FractalCollection;\nuse Illuminate\\Database\\Eloquent\\Collection as EloquentCollection;\nuse Illuminate\\Contracts\\Pagination\\Paginator as IlluminatePaginator;\n\nclass Fractal implements Adapter\n{\n    /**\n     * Fractal manager instance.\n     *\n     * @var \\League\\Fractal\\Manager\n     */\n    protected $fractal;\n\n    /**\n     * The include query string key.\n     *\n     * @var string\n     */\n    protected $includeKey;\n\n    /**\n     * The include separator.\n     *\n     * @var string\n     */\n    protected $includeSeparator;\n\n    /**\n     * Indicates if eager loading is enabled.\n     *\n     * @var bool\n     */\n    protected $eagerLoading = true;\n\n    /**\n     * Create a new fractal transformer instance.\n     *\n     * @param \\League\\Fractal\\Manager $fractal\n     * @param string                  $includeKey\n     * @param string                  $includeSeparator\n     * @param bool                    $eagerLoading\n     *\n     * @return void\n     */\n    public function __construct(FractalManager $fractal, $includeKey = 'include', $includeSeparator = ',', $eagerLoading = true)\n    {\n        $this->fractal = $fractal;\n        $this->includeKey = $includeKey;\n        $this->includeSeparator = $includeSeparator;\n        $this->eagerLoading = $eagerLoading;\n    }\n\n    /**\n     * Transform a response with a transformer.\n     *\n     * @param mixed                                     $response\n     * @param League\\Fractal\\TransformerAbstract|object $transformer\n     * @param \\Dingo\\Api\\Transformer\\Binding            $binding\n     * @param \\Dingo\\Api\\Http\\Request                   $request\n     *\n     * @return array\n     */\n    public function transform($response, $transformer, Binding $binding, Request $request)\n    {\n        $this->parseFractalIncludes($request);\n\n        $resource = $this->createResource($response, $transformer, $parameters = $binding->getParameters());\n\n        // If the response is a paginator then we'll create a new paginator\n        // adapter for Laravel and set the paginator instance on our\n        // collection resource.\n        if ($response instanceof IlluminatePaginator) {\n            $paginator = $this->createPaginatorAdapter($response);\n\n            $resource->setPaginator($paginator);\n        }\n\n        if ($this->shouldEagerLoad($response)) {\n            $eagerLoads = $this->mergeEagerLoads($transformer, $this->fractal->getRequestedIncludes());\n\n            if ($transformer instanceof TransformerAbstract) {\n                // Only eager load the items in available includes\n                $eagerLoads = array_intersect($eagerLoads, $transformer->getAvailableIncludes());\n            }\n\n            $response->load($eagerLoads);\n        }\n\n        foreach ($binding->getMeta() as $key => $value) {\n            $resource->setMetaValue($key, $value);\n        }\n\n        $binding->fireCallback($resource, $this->fractal);\n\n        $identifier = isset($parameters['identifier']) ? $parameters['identifier'] : null;\n\n        return $this->fractal->createData($resource, $identifier)->toArray();\n    }\n\n    /**\n     * Eager loading is only performed when the response is or contains an\n     * Eloquent collection and eager loading is enabled.\n     *\n     * @param mixed $response\n     *\n     * @return bool\n     */\n    protected function shouldEagerLoad($response)\n    {\n        if ($response instanceof IlluminatePaginator) {\n            $response = $response->getCollection();\n        }\n\n        return $response instanceof EloquentCollection && $this->eagerLoading;\n    }\n\n    /**\n     * Create the Fractal paginator adapter.\n     *\n     * @param \\Illuminate\\Contracts\\Pagination\\Paginator $paginator\n     *\n     * @return \\League\\Fractal\\Pagination\\IlluminatePaginatorAdapter\n     */\n    protected function createPaginatorAdapter(IlluminatePaginator $paginator)\n    {\n        return new IlluminatePaginatorAdapter($paginator);\n    }\n\n    /**\n     * Create a Fractal resource instance.\n     *\n     * @param mixed                               $response\n     * @param \\League\\Fractal\\TransformerAbstract $transformer\n     * @param array                               $parameters\n     *\n     * @return \\League\\Fractal\\Resource\\Item|\\League\\Fractal\\Resource\\Collection\n     */\n    protected function createResource($response, $transformer, array $parameters)\n    {\n        $key = isset($parameters['key']) ? $parameters['key'] : null;\n\n        if ($response instanceof IlluminatePaginator || $response instanceof IlluminateCollection) {\n            return new FractalCollection($response, $transformer, $key);\n        }\n\n        return new FractalItem($response, $transformer, $key);\n    }\n\n    /**\n     * Parse the includes.\n     *\n     * @param \\Dingo\\Api\\Http\\Request $request\n     *\n     * @return void\n     */\n    public function parseFractalIncludes(Request $request)\n    {\n        $includes = $request->input($this->includeKey);\n\n        if (! is_array($includes)) {\n            $includes = array_map('trim', array_filter(explode($this->includeSeparator, $includes)));\n        }\n\n        $this->fractal->parseIncludes($includes);\n    }\n\n    /**\n     * Get the underlying Fractal instance.\n     *\n     * @return \\League\\Fractal\\Manager\n     */\n    public function getFractal()\n    {\n        return $this->fractal;\n    }\n\n    /**\n     * Get includes as their array keys for eager loading.\n     *\n     * @param \\League\\Fractal\\TransformerAbstract $transformer\n     * @param string|array                        $requestedIncludes\n     *\n     * @return array\n     */\n    protected function mergeEagerLoads($transformer, $requestedIncludes)\n    {\n        $includes = array_merge($requestedIncludes, $transformer->getDefaultIncludes());\n\n        $eagerLoads = [];\n\n        foreach ($includes as $key => $value) {\n            $eagerLoads[] = is_string($key) ? $key : $value;\n        }\n\n        if (property_exists($transformer, 'lazyLoadedIncludes')) {\n            $eagerLoads = array_diff($eagerLoads, $transformer->lazyLoadedIncludes);\n        }\n\n        return $eagerLoads;\n    }\n\n    /**\n     * Disable eager loading.\n     *\n     * @return \\Dingo\\Api\\Transformer\\Adapter\\Fractal\n     */\n    public function disableEagerLoading()\n    {\n        $this->eagerLoading = false;\n\n        return $this;\n    }\n\n    /**\n     * Enable eager loading.\n     *\n     * @return \\Dingo\\Api\\Transformer\\Adapter\\Fractal\n     */\n    public function enableEagerLoading()\n    {\n        $this->eagerLoading = true;\n\n        return $this;\n    }\n}\n"
  },
  {
    "path": "src/Transformer/Binding.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Transformer;\n\nuse Closure;\nuse RuntimeException;\nuse Illuminate\\Container\\Container;\n\nclass Binding\n{\n    /**\n     * Illuminate container instance.\n     *\n     * @var \\Illuminate\\Container\\Container\n     */\n    protected $container;\n\n    /**\n     * Binding resolver.\n     *\n     * @var mixed\n     */\n    protected $resolver;\n\n    /**\n     * Array of parameters.\n     *\n     * @var array\n     */\n    protected $parameters = [];\n\n    /**\n     * Callback fired during transformation.\n     *\n     * @var \\Closure\n     */\n    protected $callback;\n\n    /**\n     * Array of meta data.\n     *\n     * @var array\n     */\n    protected $meta = [];\n\n    /**\n     * Create a new binding instance.\n     *\n     * @param \\Illuminate\\Container\\Container $container\n     * @param mixed                           $resolver\n     * @param array                           $parameters\n     * @param \\Closure                        $callback\n     *\n     * @return void\n     */\n    public function __construct(Container $container, $resolver, array $parameters = [], Closure $callback = null)\n    {\n        $this->container = $container;\n        $this->resolver = $resolver;\n        $this->parameters = $parameters;\n        $this->callback = $callback;\n    }\n\n    /**\n     * Resolve a transformer binding instance.\n     *\n     * @throws \\RuntimeException\n     *\n     * @return object\n     */\n    public function resolveTransformer()\n    {\n        if (is_string($this->resolver)) {\n            return $this->container->make($this->resolver);\n        } elseif (is_callable($this->resolver)) {\n            return call_user_func($this->resolver, $this->container);\n        } elseif (is_object($this->resolver)) {\n            return $this->resolver;\n        }\n\n        throw new RuntimeException('Unable to resolve transformer binding.');\n    }\n\n    /**\n     * Fire the binding callback.\n     *\n     * @param string|array $parameters\n     *\n     * @return void\n     */\n    public function fireCallback($parameters = null)\n    {\n        if (is_callable($this->callback)) {\n            call_user_func_array($this->callback, func_get_args());\n        }\n    }\n\n    /**\n     * Get the binding parameters.\n     *\n     * @return array\n     */\n    public function getParameters()\n    {\n        return $this->parameters;\n    }\n\n    /**\n     * Set the meta data for the binding.\n     *\n     * @param array $meta\n     *\n     * @return void\n     */\n    public function setMeta(array $meta)\n    {\n        $this->meta = $meta;\n    }\n\n    /**\n     * Add a meta data key/value pair.\n     *\n     * @param string $key\n     * @param mixed  $value\n     *\n     * @return void\n     */\n    public function addMeta($key, $value)\n    {\n        $this->meta[$key] = $value;\n    }\n\n    /**\n     * Get the binding meta data.\n     *\n     * @return array\n     */\n    public function getMeta()\n    {\n        return $this->meta;\n    }\n}\n"
  },
  {
    "path": "src/Transformer/Factory.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Transformer;\n\nuse Closure;\nuse RuntimeException;\nuse Dingo\\Api\\Http\\Request;\nuse Illuminate\\Support\\Collection;\nuse Illuminate\\Container\\Container;\nuse Dingo\\Api\\Contract\\Transformer\\Adapter;\nuse Illuminate\\Contracts\\Pagination\\Paginator;\nuse Illuminate\\Http\\Request as IlluminateRequest;\n\nclass Factory\n{\n    /**\n     * Illuminate container instance.\n     *\n     * @var \\Illuminate\\Container\\Container\n     */\n    protected $container;\n\n    /**\n     * Array of registered transformer bindings.\n     *\n     * @var array\n     */\n    protected $bindings = [];\n\n    /**\n     * Transformation layer adapter being used to transform responses.\n     *\n     * @var \\Dingo\\Api\\Contract\\Transformer\\Adapter\n     */\n    protected $adapter;\n\n    /**\n     * Create a new transformer factory instance.\n     *\n     * @param \\Illuminate\\Container\\Container         $container\n     * @param \\Dingo\\Api\\Contract\\Transformer\\Adapter $adapter\n     *\n     * @return void\n     */\n    public function __construct(Container $container, Adapter $adapter)\n    {\n        $this->container = $container;\n        $this->adapter = $adapter;\n    }\n\n    /**\n     * Register a transformer binding resolver for a class.\n     *\n     * @param               $class\n     * @param               $resolver\n     * @param array         $parameters\n     * @param \\Closure|null $after\n     *\n     * @return \\Dingo\\Api\\Transformer\\Binding\n     */\n    public function register($class, $resolver, array $parameters = [], Closure $after = null)\n    {\n        return $this->bindings[$class] = $this->createBinding($resolver, $parameters, $after);\n    }\n\n    /**\n     * Transform a response.\n     *\n     * @param string|object $response\n     *\n     * @return mixed\n     */\n    public function transform($response)\n    {\n        $binding = $this->getBinding($response);\n\n        return $this->adapter->transform($response, $binding->resolveTransformer(), $binding, $this->getRequest());\n    }\n\n    /**\n     * Determine if a response is transformable.\n     *\n     * @param mixed $response\n     *\n     * @return bool\n     */\n    public function transformableResponse($response)\n    {\n        return $this->transformableType($response) && $this->hasBinding($response);\n    }\n\n    /**\n     * Determine if a value is of a transformable type.\n     *\n     * @param mixed $value\n     *\n     * @return bool\n     */\n    public function transformableType($value)\n    {\n        return is_object($value) || is_string($value);\n    }\n\n    /**\n     * Get a registered transformer binding.\n     *\n     * @param string|object $class\n     *\n     * @throws \\RuntimeException\n     *\n     * @return \\Dingo\\Api\\Transformer\\Binding\n     */\n    public function getBinding($class)\n    {\n        if ($this->isCollection($class) && ! $class->isEmpty()) {\n            return $this->getBindingFromCollection($class);\n        }\n\n        $class = is_object($class) ? get_class($class) : $class;\n\n        if (! $this->hasBinding($class)) {\n            throw new RuntimeException('Unable to find bound transformer for \"'.$class.'\" class.');\n        }\n\n        return $this->bindings[$class];\n    }\n\n    /**\n     * Create a new binding instance.\n     *\n     * @param string|callable|object $resolver\n     * @param array                  $parameters\n     * @param \\Closure               $callback\n     *\n     * @return \\Dingo\\Api\\Transformer\\Binding\n     */\n    protected function createBinding($resolver, array $parameters = [], Closure $callback = null)\n    {\n        return new Binding($this->container, $resolver, $parameters, $callback);\n    }\n\n    /**\n     * Get a registered transformer binding from a collection of items.\n     *\n     * @param \\Illuminate\\Support\\Collection $collection\n     *\n     * @return null|string|callable\n     */\n    protected function getBindingFromCollection($collection)\n    {\n        return $this->getBinding($collection->first());\n    }\n\n    /**\n     * Determine if a class has a transformer binding.\n     *\n     * @param string|object $class\n     *\n     * @return bool\n     */\n    protected function hasBinding($class)\n    {\n        if ($this->isCollection($class) && ! $class->isEmpty()) {\n            $class = $class->first();\n        }\n\n        $class = is_object($class) ? get_class($class) : $class;\n\n        return isset($this->bindings[$class]);\n    }\n\n    /**\n     * Determine if the instance is a collection.\n     *\n     * @param object $instance\n     *\n     * @return bool\n     */\n    protected function isCollection($instance)\n    {\n        return $instance instanceof Collection || $instance instanceof Paginator;\n    }\n\n    /**\n     * Get the array of registered transformer bindings.\n     *\n     * @return array\n     */\n    public function getTransformerBindings()\n    {\n        return $this->bindings;\n    }\n\n    /**\n     * Set the transformation layer at runtime.\n     *\n     * @param \\Closure|\\Dingo\\Api\\Contract\\Transformer\\Adapter $adapter\n     *\n     * @return void\n     */\n    public function setAdapter($adapter)\n    {\n        if (is_callable($adapter)) {\n            $adapter = call_user_func($adapter, $this->container);\n        }\n\n        $this->adapter = $adapter;\n    }\n\n    /**\n     * Get the transformation layer adapter.\n     *\n     * @return \\Dingo\\Api\\Contract\\Transformer\\Adapter\n     */\n    public function getAdapter()\n    {\n        return $this->adapter;\n    }\n\n    /**\n     * Get the request from the container.\n     *\n     * @return \\Dingo\\Api\\Http\\Request\n     */\n    public function getRequest()\n    {\n        $request = $this->container['request'];\n\n        if ($request instanceof IlluminateRequest && ! $request instanceof Request) {\n            $request = (new Request())->createFromIlluminate($request);\n        }\n\n        return $request;\n    }\n\n    /**\n     * Pass unknown method calls through to the adapter.\n     *\n     * @param string $method\n     * @param array  $parameters\n     *\n     * @return mixed\n     */\n    public function __call($method, $parameters)\n    {\n        return call_user_func_array([$this->adapter, $method], $parameters);\n    }\n}\n"
  },
  {
    "path": "src/helpers.php",
    "content": "<?php\n\nif (! function_exists('version')) {\n    /**\n     * Set the version to generate API URLs to.\n     *\n     * @param string $version\n     *\n     * @return \\Dingo\\Api\\Routing\\UrlGenerator\n     */\n    function version($version)\n    {\n        return app('api.url')->version($version);\n    }\n}\n"
  },
  {
    "path": "tests/Auth/AuthTest.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Tests\\Auth;\n\nuse Dingo\\Api\\Auth\\Auth;\nuse Dingo\\Api\\Contract\\Auth\\Provider;\nuse Dingo\\Api\\Http\\Request;\nuse Dingo\\Api\\Routing\\Route;\nuse Dingo\\Api\\Routing\\Router;\nuse Dingo\\Api\\Tests\\BaseTestCase;\nuse Illuminate\\Container\\Container;\nuse Mockery as m;\nuse Symfony\\Component\\HttpKernel\\Exception\\BadRequestHttpException;\nuse Symfony\\Component\\HttpKernel\\Exception\\UnauthorizedHttpException;\n\nclass AuthTest extends BaseTestCase\n{\n    /**\n     * @var Container\n     */\n    protected $container;\n    /**\n     * @var Router|m\\LegacyMockInterface|m\\MockInterface\n     */\n    protected $router;\n    /**\n     * @var Auth\n     */\n    protected $auth;\n\n    public function setUp(): void\n    {\n        parent::setUp();\n\n        $this->container = new Container;\n        $this->router = m::mock(Router::class);\n        $this->auth = new Auth($this->router, $this->container, []);\n    }\n\n    public function testExceptionThrownWhenAuthorizationHeaderNotSet()\n    {\n        $this->expectException(UnauthorizedHttpException::class);\n\n        $this->router->shouldReceive('getCurrentRoute')->once()->andReturn($route = m::mock(Route::class));\n        $this->router->shouldReceive('getCurrentRequest')->once()->andReturn($request = Request::create('foo', 'GET'));\n\n        $provider = m::mock(Provider::class);\n        $provider->shouldReceive('authenticate')->once()->with($request, $route)->andThrow(new BadRequestHttpException);\n\n        $this->auth->extend('provider', $provider);\n\n        $this->auth->authenticate();\n    }\n\n    public function testExceptionThrownWhenProviderFailsToAuthenticate()\n    {\n        $this->expectException(UnauthorizedHttpException::class);\n\n        $this->router->shouldReceive('getCurrentRoute')->once()->andReturn($route = m::mock(Route::class));\n        $this->router->shouldReceive('getCurrentRequest')->once()->andReturn($request = Request::create('foo', 'GET'));\n\n        $provider = m::mock(Provider::class);\n        $provider->shouldReceive('authenticate')->once()->with($request, $route)->andThrow(new UnauthorizedHttpException('foo'));\n\n        $this->auth->extend('provider', $provider);\n\n        $this->auth->authenticate();\n    }\n\n    public function testAuthenticationIsSuccessfulAndUserIsSet()\n    {\n        $this->router->shouldReceive('getCurrentRoute')->once()->andReturn($route = m::mock(Route::class));\n        $this->router->shouldReceive('getCurrentRequest')->once()->andReturn($request = Request::create('foo', 'GET'));\n\n        $provider = m::mock(Provider::class);\n        $provider->shouldReceive('authenticate')->once()->with($request, $route)->andReturn((object) ['id' => 1]);\n\n        $this->auth->extend('provider', $provider);\n\n        $user = $this->auth->authenticate();\n\n        $this->assertSame(1, $user->id);\n    }\n\n    public function testProvidersAreFilteredWhenSpecificProviderIsRequested()\n    {\n        $this->router->shouldReceive('getCurrentRoute')->once()->andReturn($route = m::mock(Route::class));\n        $this->router->shouldReceive('getCurrentRequest')->once()->andReturn($request = Request::create('foo', 'GET'));\n\n        $provider = m::mock(Provider::class);\n        $provider->shouldReceive('authenticate')->once()->with($request, $route)->andReturn((object) ['id' => 1]);\n\n        $this->auth->extend('one', m::mock(Provider::class));\n        $this->auth->extend('two', $provider);\n\n        $this->auth->authenticate(['two']);\n        $this->assertSame($provider, $this->auth->getProviderUsed());\n    }\n\n    public function testGettingUserWhenNotAuthenticatedAttemptsToAuthenticateAndReturnsNull()\n    {\n        $this->router->shouldReceive('getCurrentRoute')->once()->andReturn(m::mock(Route::class));\n        $this->router->shouldReceive('getCurrentRequest')->once()->andReturn(Request::create('foo', 'GET'));\n\n        $this->auth->extend('provider', m::mock(Provider::class));\n\n        $this->assertNull($this->auth->user());\n    }\n\n    public function testGettingUserWhenAlreadyAuthenticatedReturnsUser()\n    {\n        $this->auth->setUser((object) ['id' => 1]);\n\n        $this->assertSame(1, $this->auth->user()->id);\n        $this->assertTrue($this->auth->check());\n    }\n}\n"
  },
  {
    "path": "tests/Auth/Provider/AuthorizationTest.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Tests\\Auth\\Provider;\n\nuse Dingo\\Api\\Routing\\Route;\nuse Dingo\\Api\\Tests\\BaseTestCase;\nuse Dingo\\Api\\Tests\\Stubs\\AuthorizationProviderStub;\nuse Illuminate\\Http\\Request;\nuse Mockery as m;\nuse Symfony\\Component\\HttpKernel\\Exception\\BadRequestHttpException;\n\nclass AuthorizationTest extends BaseTestCase\n{\n    public function testExceptionThrownWhenAuthorizationHeaderIsInvalid()\n    {\n        $this->expectException(BadRequestHttpException::class);\n\n        $request = Request::create('GET', '/');\n\n        (new AuthorizationProviderStub)->authenticate($request, m::mock(Route::class));\n    }\n}\n"
  },
  {
    "path": "tests/Auth/Provider/BasicTest.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Tests\\Auth\\Provider;\n\nuse Dingo\\Api\\Auth\\Provider\\Basic;\nuse Dingo\\Api\\Routing\\Route;\nuse Dingo\\Api\\Tests\\BaseTestCase;\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Http\\Response;\nuse Mockery as m;\nuse Symfony\\Component\\HttpKernel\\Exception\\UnauthorizedHttpException;\n\nclass BasicTest extends BaseTestCase\n{\n    protected $auth;\n    protected $provider;\n\n    public function setUp(): void\n    {\n        parent::setUp();\n\n        $this->auth = m::mock('Illuminate\\Auth\\AuthManager');\n        $this->provider = new Basic($this->auth);\n    }\n\n    public function testInvalidBasicCredentialsThrowsException()\n    {\n        $this->expectException(UnauthorizedHttpException::class);\n\n        $request = Request::create('GET', '/', [], [], [], ['HTTP_AUTHORIZATION' => 'Basic 12345']);\n\n        $this->auth->shouldReceive('onceBasic')->once()->with('email')->andReturn(new Response('', 401));\n\n        $this->provider->authenticate($request, m::mock(Route::class));\n    }\n\n    public function testValidCredentialsReturnsUser()\n    {\n        $request = Request::create('GET', '/', [], [], [], ['HTTP_AUTHORIZATION' => 'Basic 12345']);\n\n        $this->auth->shouldReceive('onceBasic')->once()->with('email')->andReturn(null);\n        $this->auth->shouldReceive('user')->once()->andReturn('foo');\n\n        $this->assertSame('foo', $this->provider->authenticate($request, m::mock(Route::class)));\n    }\n}\n"
  },
  {
    "path": "tests/Auth/Provider/JWTTest.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Tests\\Auth\\Provider;\n\nuse Dingo\\Api\\Auth\\Provider\\JWT;\nuse Dingo\\Api\\Routing\\Route;\nuse Dingo\\Api\\Tests\\BaseTestCase;\nuse Illuminate\\Http\\Request;\nuse Mockery as m;\nuse Symfony\\Component\\HttpKernel\\Exception\\BadRequestHttpException;\nuse Symfony\\Component\\HttpKernel\\Exception\\UnauthorizedHttpException;\nuse Tymon\\JWTAuth\\Exceptions\\JWTException;\n\nclass JWTTest extends BaseTestCase\n{\n    protected $auth;\n    protected $provider;\n\n    public function setUp(): void\n    {\n        parent::setUp();\n\n        $this->auth = m::mock('Tymon\\JWTAuth\\JWTAuth');\n        $this->provider = new JWT($this->auth);\n    }\n\n    public function testValidatingAuthorizationHeaderFailsAndThrowsException()\n    {\n        $this->expectException(BadRequestHttpException::class);\n\n        $request = Request::create('foo', 'GET');\n        $this->provider->authenticate($request, m::mock(Route::class));\n    }\n\n    public function testAuthenticatingFailsAndThrowsException()\n    {\n        $this->expectException(UnauthorizedHttpException::class);\n\n        $request = Request::create('foo', 'GET');\n        $request->headers->set('authorization', 'Bearer foo');\n\n        $this->auth->shouldReceive('setToken')->with('foo')->andReturn(m::self());\n        $this->auth->shouldReceive('authenticate')->once()->andThrow(new JWTException('foo'));\n\n        $this->provider->authenticate($request, m::mock(Route::class));\n    }\n\n    public function testAuthenticatingSucceedsAndReturnsUserObject()\n    {\n        $request = Request::create('foo', 'GET');\n        $request->headers->set('authorization', 'Bearer foo');\n\n        $this->auth->shouldReceive('setToken')->with('foo')->andReturn(m::self());\n        $this->auth->shouldReceive('authenticate')->once()->andReturn((object) ['id' => 1]);\n\n        $this->assertSame(1, $this->provider->authenticate($request, m::mock(Route::class))->id);\n    }\n\n    public function testAuthenticatingWithQueryStringSucceedsAndReturnsUserObject()\n    {\n        $request = Request::create('foo', 'GET', ['token' => 'foo']);\n\n        $this->auth->shouldReceive('setToken')->with('foo')->andReturn(m::self());\n        $this->auth->shouldReceive('authenticate')->once()->andReturn((object) ['id' => 1]);\n\n        $this->assertSame(1, $this->provider->authenticate($request, m::mock(Route::class))->id);\n    }\n}\n"
  },
  {
    "path": "tests/BaseTestCase.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Tests;\n\nuse Dingo\\Api\\Http\\Response;\nuse Mockery;\nuse PHPUnit\\Framework\\TestCase;\n\nclass BaseTestCase extends TestCase\n{\n    public function tearDown(): void\n    {\n        parent::tearDown();\n        // make sure mocker is cleaned up\n        Mockery::close();\n        // reset response formatters on tear down\n        Response::setFormatters([]);\n        Response::setFormatsOptions([]);\n    }\n\n    public function setUp(): void\n    {\n        parent::setUp();\n    }\n}\n"
  },
  {
    "path": "tests/ChecksLaravelVersionTrait.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Tests;\n\nuse Dingo\\Api\\Tests\\Stubs\\ApplicationStub;\nuse Dingo\\Api\\Tests\\Stubs\\Application8Stub;\nuse Dingo\\Api\\Tests\\Stubs\\Application7Stub;\nuse Dingo\\Api\\Tests\\Stubs\\Application6Stub;\nuse Dingo\\Api\\Tests\\Stubs\\Application58Stub;\n\ntrait ChecksLaravelVersionTrait\n{\n    public $installed_file_path = __DIR__.'/../vendor/composer/installed.json';\n    public $current_release = '8.0';\n\n    private function getFrameworkVersion()\n    {\n        $contents = file_get_contents($this->installed_file_path);\n        $parsed_data = json_decode($contents, true);\n\n        // Changed array format in newer versions of composer (v2?)\n        if (array_key_exists('packages', $parsed_data)) {\n            $parsed_data = $parsed_data['packages'];\n        }\n\n        // Find laravel/framework or lumen package\n        $just_laravel = array_filter($parsed_data, function ($composerPackageData) {\n            if (is_array($composerPackageData) && array_key_exists('name', $composerPackageData)) {\n                if ('laravel/framework' === $composerPackageData['name'] || 'laravel/lumen-framework' === $composerPackageData['name']) {\n                    return true;\n                }\n            }\n        });\n\n        if (empty($just_laravel)) {\n            exit(PHP_EOL.'No Laravel version detected, please do a \"composer require laravel/framework:x\" prior to testing'.PHP_EOL);\n        }\n\n        $laravelVersion = array_map(function ($val) {\n            return $val['version'];\n        }, array_values($just_laravel))[0];\n\n        return $laravelVersion;\n    }\n\n    private function getApplicationStub()\n    {\n        $version = $this->getFrameworkVersion();\n        if ('dev-master' === $version) {\n            $version = $this->current_release;\n        }\n\n        // Remove the 'v' in for example 'v5.8.3'\n        $version = str_replace('v', '', $version);\n\n        // Return the version stub for the right version\n        if (version_compare($version, '8.0.0', '>=')) {\n            return new Application8Stub;\n        } elseif (version_compare($version, '7.0.0', '>=')) {\n            return new Application7Stub;\n        } elseif (version_compare($version, '6.0.0', '>=')) {\n            return new Application6Stub;\n        } elseif (version_compare($version, '5.8.0', '>=')) {\n            return new Application58Stub;\n        } else {\n            return new ApplicationStub;\n        }\n    }\n}\n"
  },
  {
    "path": "tests/DispatcherTest.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Tests;\n\nuse Dingo\\Api\\Auth\\Auth;\nuse Dingo\\Api\\Dispatcher;\nuse Dingo\\Api\\Exception\\Handler;\nuse Dingo\\Api\\Exception\\InternalHttpException;\nuse Dingo\\Api\\Exception\\ValidationHttpException;\nuse Dingo\\Api\\Http;\nuse Dingo\\Api\\Http\\Response;\nuse Dingo\\Api\\Routing\\Router;\nuse Dingo\\Api\\Tests\\Stubs\\MiddlewareStub;\nuse Dingo\\Api\\Tests\\Stubs\\RoutingAdapterStub;\nuse Dingo\\Api\\Tests\\Stubs\\TransformerStub;\nuse Dingo\\Api\\Tests\\Stubs\\UserStub;\nuse Dingo\\Api\\Tests\\Stubs\\UserTransformerStub;\nuse Dingo\\Api\\Transformer\\Factory as TransformerFactory;\nuse Illuminate\\Container\\Container;\nuse Illuminate\\Filesystem\\Filesystem;\nuse Illuminate\\Http\\JsonResponse;\nuse Illuminate\\Http\\RedirectResponse;\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Support\\Facades\\Request as RequestFacade;\nuse Mockery as m;\nuse Symfony\\Component\\HttpKernel\\Exception\\GoneHttpException;\n\nclass DispatcherTest extends BaseTestCase\n{\n    /**\n     * @var Container\n     */\n    protected $container;\n    /**\n     * @var TransformerFactory\n     */\n    protected $transformerFactory;\n    /**\n     * @var Dispatcher\n     */\n    protected $dispatcher;\n    /**\n     * @var RoutingAdapterStub\n     */\n    protected $adapter;\n    /**\n     * @var Handler|m\\LegacyMockInterface|m\\MockInterface\n     */\n    protected $exception;\n    /**\n     * @var Router\n     */\n    protected $router;\n    /**\n     * @var Auth\n     */\n    protected $auth;\n\n    public function setUp(): void\n    {\n        $this->container = new Container;\n        $this->container['request'] = Request::create('/', 'GET');\n        $this->container['api.auth'] = new MiddlewareStub;\n        $this->container['api.limiting'] = new MiddlewareStub;\n\n        Http\\Request::setAcceptParser(new Http\\Parser\\Accept('vnd', 'api', 'v1', 'json'));\n\n        $this->transformerFactory = new TransformerFactory($this->container, new TransformerStub);\n\n        $this->adapter = new RoutingAdapterStub;\n        $this->exception = m::mock(Handler::class);\n        $this->router = new Router($this->adapter, $this->exception, $this->container, null, null);\n\n        $this->auth = new Auth($this->router, $this->container, []);\n        $this->dispatcher = new Dispatcher($this->container, new Filesystem, $this->router, $this->auth);\n\n        app()->instance(\\Illuminate\\Routing\\Router::class, $this->adapter);\n\n        $this->dispatcher->setSubtype('api');\n        $this->dispatcher->setStandardsTree('vnd');\n        $this->dispatcher->setDefaultVersion('v1');\n        $this->dispatcher->setDefaultFormat('json');\n\n        Response::setFormatters(['json' => new Http\\Response\\Format\\Json]);\n        Response::setTransformer($this->transformerFactory);\n    }\n\n    public function testInternalRequests()\n    {\n        $this->router->version('v1', function () {\n            $this->router->get('test', function () {\n                return 'foo';\n            });\n\n            $this->router->post('test', function () {\n                return 'bar';\n            });\n\n            $this->router->put('test', function () {\n                return 'baz';\n            });\n\n            $this->router->patch('test', function () {\n                return 'yin';\n            });\n\n            $this->router->delete('test', function () {\n                return 'yang';\n            });\n        });\n\n        $this->assertSame('foo', $this->dispatcher->get('test'));\n        $this->assertSame('bar', $this->dispatcher->post('test'));\n        $this->assertSame('baz', $this->dispatcher->put('test'));\n        $this->assertSame('yin', $this->dispatcher->patch('test'));\n        $this->assertSame('yang', $this->dispatcher->delete('test'));\n    }\n\n    public function testInternalRequestWithVersionAndParameters()\n    {\n        $this->router->version('v1', function () {\n            $this->router->get('test', function () {\n                return 'test';\n            });\n        });\n\n        $this->assertSame('test', $this->dispatcher->version('v1')->with(['foo' => 'bar'])->get('test'));\n    }\n\n    public function testInternalRequestWithPrefix()\n    {\n        $this->router->version('v1', ['prefix' => 'baz'], function () {\n            $this->router->get('test', function () {\n                return 'test';\n            });\n        });\n\n        $this->assertSame('test', $this->dispatcher->get('baz/test'));\n\n        $this->dispatcher->setPrefix('baz');\n\n        $this->assertSame('test', $this->dispatcher->get('test'));\n    }\n\n    public function testInternalRequestWithDomain()\n    {\n        $this->router->version('v1', ['domain' => 'foo.bar'], function () {\n            $this->router->get('test', function () {\n                return 'test';\n            });\n        });\n\n        $this->assertSame('test', $this->dispatcher->get('http://foo.bar/test'));\n\n        $this->dispatcher->setDefaultDomain('foo.bar');\n\n        $this->assertSame('test', $this->dispatcher->get('test'));\n    }\n\n    public function testInternalRequestThrowsExceptionWhenResponseIsNotOkay()\n    {\n        $this->expectException(InternalHttpException::class);\n\n        $this->router->version('v1', function () {\n            $this->router->get('test', function () {\n                return new \\Illuminate\\Http\\Response('test', 403);\n            });\n        });\n\n        $this->dispatcher->get('test');\n    }\n\n    public function testInternalExceptionContainsResponseObject()\n    {\n        $this->router->version('v1', function () {\n            $this->router->get('test', function () {\n                return new \\Illuminate\\Http\\Response('test', 401);\n            });\n        });\n\n        try {\n            $this->dispatcher->get('test');\n        } catch (InternalHttpException $exception) {\n            $this->assertInstanceOf(\\Illuminate\\Http\\Response::class, $exception->getResponse());\n            $this->assertSame('test', $exception->getResponse()->getContent());\n        }\n    }\n\n    public function testThrowingHttpExceptionFallsThroughRouter()\n    {\n        $this->router->version('v1', function () {\n            $this->router->get('test', function () {\n                throw new GoneHttpException;\n            });\n        });\n\n        $passed = false;\n\n        try {\n            $this->dispatcher->get('test');\n        } catch (GoneHttpException $exception) {\n            $passed = true;\n        }\n\n        $this->assertTrue($passed);\n    }\n\n    public function testPretendingToBeUserForSingleRequest()\n    {\n        $user = m::mock('Illuminate\\Database\\Eloquent\\Model');\n\n        $this->router->version('v1', function () use ($user) {\n            $this->router->get('test', function () use ($user) {\n                $this->assertSame($user, $this->auth->user());\n            });\n        });\n\n        $this->dispatcher->be($user)->once()->get('test');\n    }\n\n    public function testInternalRequestWithMultipleVersionsCallsCorrectVersion()\n    {\n        $this->router->version('v1', function () {\n            $this->router->get('foo', function () {\n                return 'foo';\n            });\n        });\n\n        $this->router->version(['v2', 'v3'], function () {\n            $this->router->get('foo', function () {\n                return 'bar';\n            });\n        });\n\n        $this->assertSame('foo', $this->dispatcher->version('v1')->get('foo'));\n        $this->assertSame('bar', $this->dispatcher->version('v2')->get('foo'));\n        $this->assertSame('bar', $this->dispatcher->version('v3')->get('foo'));\n    }\n\n    public function testInternalRequestWithNestedInternalRequest()\n    {\n        $this->router->version('v1', function () {\n            $this->router->get('foo', function () {\n                return 'foo'.$this->dispatcher->version('v2')->get('foo');\n            });\n        });\n\n        $this->router->version('v2', function () {\n            $this->router->get('foo', function () {\n                return 'bar'.$this->dispatcher->version('v3')->get('foo');\n            });\n        });\n\n        $this->router->version('v3', function () {\n            $this->router->get('foo', function () {\n                return 'baz';\n            });\n        });\n\n        $this->assertSame('foobarbaz', $this->dispatcher->get('foo'));\n    }\n\n    public function testRequestStackIsMaintained()\n    {\n        $this->router->version('v1', ['prefix' => 'api'], function () {\n            $this->router->post('foo', function () {\n                $this->assertSame('bar', $this->router->getCurrentRequest()->input('foo'));\n                $this->dispatcher->with(['foo' => 'baz'])->post('api/bar');\n                $this->assertSame('bar', $this->router->getCurrentRequest()->input('foo'));\n            });\n\n            $this->router->post('bar', function () {\n                $this->assertSame('baz', $this->router->getCurrentRequest()->input('foo'));\n                $this->dispatcher->with(['foo' => 'bazinga'])->post('api/baz');\n                $this->assertSame('baz', $this->router->getCurrentRequest()->input('foo'));\n            });\n\n            $this->router->post('baz', function () {\n                $this->assertSame('bazinga', $this->router->getCurrentRequest()->input('foo'));\n            });\n        });\n\n        $this->dispatcher->with(['foo' => 'bar'])->post('api/foo');\n    }\n\n    public function testRouteStackIsMaintained()\n    {\n        $this->router->version('v1', function () {\n            $this->router->post('foo', ['as' => 'foo', function () {\n                $this->assertSame('foo', $this->router->getCurrentRoute()->getName());\n                $this->dispatcher->post('bar');\n                $this->assertSame('foo', $this->router->getCurrentRoute()->getName());\n            }]);\n\n            $this->router->post('bar', ['as' => 'bar', function () {\n                $this->assertSame('bar', $this->router->getCurrentRoute()->getName());\n                $this->dispatcher->post('baz');\n                $this->assertSame('bar', $this->router->getCurrentRoute()->getName());\n            }]);\n\n            $this->router->post('baz', ['as' => 'bazinga', function () {\n                $this->assertSame('bazinga', $this->router->getCurrentRoute()->getName());\n            }]);\n        });\n\n        $this->dispatcher->post('foo');\n    }\n\n    public function testSendingJsonPayload()\n    {\n        $this->router->version('v1', function () {\n            $this->router->post('foo', function () {\n                $this->assertSame('jason', $this->router->getCurrentRequest()->json('username'));\n            });\n\n            $this->router->post('bar', function () {\n                $this->assertSame('mat', $this->router->getCurrentRequest()->json('username'));\n            });\n        });\n\n        $this->dispatcher->json(['username' => 'jason'])->post('foo');\n        $this->dispatcher->json('{\"username\":\"mat\"}')->post('bar');\n    }\n\n    public function testInternalRequestsToDifferentDomains()\n    {\n        $this->router->version(['v1', 'v2'], ['domain' => 'foo.bar'], function () {\n            $this->router->get('foo', function () {\n                return 'v1 and v2 on domain foo.bar';\n            });\n        });\n\n        $this->router->version('v1', ['domain' => 'foo.baz'], function () {\n            $this->router->get('foo', function () {\n                return 'v1 on domain foo.baz';\n            });\n        });\n\n        $this->router->version('v2', ['domain' => 'foo.baz'], function () {\n            $this->router->get('foo', function () {\n                return 'v2 on domain foo.baz';\n            });\n        });\n\n        $this->assertSame('v1 and v2 on domain foo.bar', $this->dispatcher->on('foo.bar')->version('v2')->get('foo'));\n        $this->assertSame('v1 on domain foo.baz', $this->dispatcher->on('foo.baz')->get('foo'));\n        $this->assertSame('v2 on domain foo.baz', $this->dispatcher->on('foo.baz')->version('v2')->get('foo'));\n    }\n\n    public function testRequestingRawResponse()\n    {\n        $this->router->version('v1', function () {\n            $this->router->get('foo', function () {\n                return ['foo' => 'bar'];\n            });\n        });\n\n        $response = $this->dispatcher->raw()->get('foo');\n\n        $this->assertInstanceOf(Response::class, $response);\n        $this->assertSame('{\"foo\":\"bar\"}', $response->getContent());\n        $this->assertSame(['foo' => 'bar'], $response->getOriginalContent());\n    }\n\n    public function testRequestingRawResponseWithTransformers()\n    {\n        $instance = null;\n\n        $this->router->version('v1', function () use (&$instance) {\n            $this->router->get('foo', function () use (&$instance) {\n                return $instance = new UserStub('Jason');\n            });\n        });\n\n        $this->transformerFactory->register(UserStub::class, UserTransformerStub::class);\n\n        $response = $this->dispatcher->raw()->get('foo');\n\n        $this->assertInstanceOf(Response::class, $response);\n        $this->assertSame('{\"name\":\"Jason\"}', $response->getContent());\n        $this->assertSame($instance, $response->getOriginalContent());\n    }\n\n    public function testUsingRequestFacadeDoesNotCacheRequestInstance()\n    {\n        RequestFacade::setFacadeApplication($this->container);\n\n        $this->router->version('v1', function () {\n            $this->router->get('foo', function () {\n                return RequestFacade::input('foo');\n            });\n        });\n\n        $this->assertNull(RequestFacade::input('foo'));\n\n        $response = $this->dispatcher->with(['foo' => 'bar'])->get('foo');\n\n        $this->assertSame('bar', $response);\n        $this->assertNull(RequestFacade::input('foo'));\n    }\n\n    public function testRedirectResponseThrowsException()\n    {\n        $this->router->version('v1', function () {\n            $this->router->get('redirect', function () {\n                return new RedirectResponse('redirect-test');\n            });\n        });\n\n        $response = $this->dispatcher->get('redirect');\n        $this->assertInstanceOf(RedirectResponse::class, $response);\n        $this->assertSame('redirect-test', $response->getTargetUrl());\n    }\n\n    public function testNotOkJsonResponseThrowsException()\n    {\n        $this->expectException(InternalHttpException::class);\n\n        $this->router->version('v1', function () {\n            $this->router->get('json', function () {\n                return new JsonResponse(['is' => 'json'], 422);\n            });\n        });\n\n        $this->dispatcher->get('json');\n    }\n\n    public function testFormRequestValidationFailureThrowsValidationException()\n    {\n        $this->expectException(ValidationHttpException::class);\n\n        $this->router->version('v1', function () {\n            $this->router->get('fail', function () {\n                //Mocking the form validation call is challenging at the moment, so next best thing\n                throw new ValidationHttpException(['foo' => 'bar']);\n            });\n        });\n\n        $this->dispatcher->get('fail');\n    }\n}\n"
  },
  {
    "path": "tests/Exception/HandlerTest.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Tests\\Exception;\n\nuse Dingo\\Api\\Exception\\Handler;\nuse Dingo\\Api\\Exception\\ResourceException;\nuse Dingo\\Api\\Http\\Request as ApiRequest;\nuse Dingo\\Api\\Tests\\BaseTestCase;\nuse Illuminate\\Http\\JsonResponse;\nuse Illuminate\\Http\\RedirectResponse;\nuse Illuminate\\Http\\Response;\nuse Mockery as m;\nuse RuntimeException;\nuse Symfony\\Component\\HttpKernel\\Exception\\HttpException;\n\nclass HandlerTest extends BaseTestCase\n{\n    protected $parentHandler;\n    protected $exceptionHandler;\n\n    public function setUp(): void\n    {\n        $this->parentHandler = m::mock('Illuminate\\Contracts\\Debug\\ExceptionHandler');\n        $this->exceptionHandler = new Handler($this->parentHandler, [\n            'message' => ':message',\n            'errors' => ':errors',\n            'code' => ':code',\n            'status_code' => ':status_code',\n            'debug' => ':debug',\n        ], false);\n    }\n\n    public function testRegisterExceptionHandler()\n    {\n        $this->exceptionHandler->register(function (HttpException $e) {\n            //\n        });\n        $this->assertArrayHasKey(HttpException::class, $this->exceptionHandler->getHandlers());\n    }\n\n    public function testExceptionHandlerHandlesException()\n    {\n        $this->exceptionHandler->register(function (HttpException $e) {\n            return new Response('foo', 404);\n        });\n\n        $exception = new HttpException(404, 'bar');\n\n        $response = $this->exceptionHandler->handle($exception);\n\n        $this->assertSame('foo', $response->getContent());\n        $this->assertSame(404, $response->getStatusCode());\n        $this->assertSame($exception, $response->exception);\n    }\n\n    public function testExceptionHandlerHandlesExceptionAndCreatesNewResponse()\n    {\n        $this->exceptionHandler->register(function (HttpException $e) {\n            return 'foo';\n        });\n\n        $exception = new HttpException(404, 'bar');\n\n        $response = $this->exceptionHandler->handle($exception);\n\n        $this->assertInstanceOf(Response::class, $response);\n        $this->assertSame('foo', $response->getContent());\n        $this->assertSame(404, $response->getStatusCode());\n    }\n\n    public function testExceptionHandlerHandlesExceptionWithRedirectResponse()\n    {\n        $this->exceptionHandler->register(function (HttpException $e) {\n            return new RedirectResponse('foo');\n        });\n\n        $exception = new HttpException(404, 'bar');\n\n        $response = $this->exceptionHandler->handle($exception);\n\n        $this->assertInstanceOf(RedirectResponse::class, $response);\n        $this->assertSame('foo', $response->getTargetUrl());\n        $this->assertSame(302, $response->getStatusCode());\n    }\n\n    public function testExceptionHandlerHandlesExceptionWithJsonResponse()\n    {\n        $this->exceptionHandler->register(function (HttpException $e) {\n            return new JsonResponse(['foo' => 'bar'], 404);\n        });\n\n        $exception = new HttpException(404, 'bar');\n\n        $response = $this->exceptionHandler->handle($exception);\n\n        $this->assertInstanceOf(JsonResponse::class, $response);\n        $this->assertSame('{\"foo\":\"bar\"}', $response->getContent());\n        $this->assertSame(404, $response->getStatusCode());\n    }\n\n    public function testExceptionHandlerReturnsGenericWhenNoMatchingHandler()\n    {\n        $exception = new HttpException(404, 'bar');\n\n        $response = $this->exceptionHandler->handle($exception);\n\n        $this->assertInstanceOf(Response::class, $response);\n        $this->assertSame('{\"message\":\"bar\",\"status_code\":404}', $response->getContent());\n        $this->assertSame(404, $response->getStatusCode());\n    }\n\n    public function testUsingMultidimensionalArrayForGenericResponse()\n    {\n        $this->exceptionHandler->setErrorFormat([\n            'error' => [\n                'message' => ':message',\n                'errors' => ':errors',\n                'code' => ':code',\n                'status_code' => ':status_code',\n                'debug' => ':debug',\n            ],\n        ]);\n\n        $exception = new HttpException(404, 'bar');\n\n        $response = $this->exceptionHandler->handle($exception);\n\n        $this->assertInstanceOf(Response::class, $response);\n        $this->assertSame('{\"error\":{\"message\":\"bar\",\"status_code\":404}}', $response->getContent());\n        $this->assertSame(404, $response->getStatusCode());\n    }\n\n    public function testRegularExceptionsAreHandledByGenericHandler()\n    {\n        $exception = new RuntimeException('Uh oh');\n\n        $response = $this->exceptionHandler->handle($exception);\n\n        $this->assertSame('{\"message\":\"Uh oh\",\"status_code\":500}', $response->getContent());\n        $this->assertSame(500, $response->getStatusCode());\n        $this->assertSame($exception, $response->exception);\n    }\n\n    public function testResourceExceptionErrorsAreIncludedInResponse()\n    {\n        $exception = new ResourceException('bar', ['foo' => 'bar'], null, [], 10);\n\n        $response = $this->exceptionHandler->handle($exception);\n\n        $this->assertInstanceOf(Response::class, $response);\n        $this->assertSame('{\"message\":\"bar\",\"errors\":{\"foo\":[\"bar\"]},\"code\":10,\"status_code\":422}', $response->getContent());\n        $this->assertSame(422, $response->getStatusCode());\n    }\n\n    public function testExceptionTraceIncludedInResponse()\n    {\n        $this->exceptionHandler->setDebug(true);\n\n        $exception = new HttpException(404, 'bar');\n\n        $response = $this->exceptionHandler->handle($exception);\n\n        $object = json_decode($response->getContent());\n\n        $this->assertObjectHasAttribute('debug', $object);\n    }\n\n    public function testHttpExceptionsWithNoMessageUseStatusCodeMessage()\n    {\n        $exception = new HttpException(404);\n\n        $response = $this->exceptionHandler->handle($exception);\n\n        $this->assertInstanceOf(Response::class, $response);\n        $this->assertSame('{\"message\":\"404 Not Found\",\"status_code\":404}', $response->getContent());\n        $this->assertSame(404, $response->getStatusCode());\n    }\n\n    public function testExceptionsHandledByRenderAreReroutedThroughHandler()\n    {\n        $request = ApiRequest::create('foo', 'GET');\n\n        $exception = new HttpException(404);\n\n        $response = $this->exceptionHandler->render($request, $exception);\n\n        $this->assertSame('{\"message\":\"404 Not Found\",\"status_code\":404}', $response->getContent());\n    }\n\n    public function testSettingUserDefinedReplacements()\n    {\n        $this->exceptionHandler->setReplacements([':foo' => 'bar']);\n        $this->exceptionHandler->setErrorFormat(['bing' => ':foo']);\n\n        $exception = new HttpException(404);\n\n        $response = $this->exceptionHandler->handle($exception);\n\n        $this->assertSame('{\"bing\":\"bar\"}', $response->getContent());\n    }\n}\n"
  },
  {
    "path": "tests/Http/Middleware/AuthTest.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Tests\\Http\\Middleware;\n\nuse Dingo\\Api\\Auth\\Auth;\nuse Dingo\\Api\\Http\\Middleware\\Auth as AuthMiddleware;\nuse Dingo\\Api\\Http\\Request;\nuse Dingo\\Api\\Routing\\Route;\nuse Dingo\\Api\\Routing\\Router;\nuse Dingo\\Api\\Tests\\BaseTestCase;\nuse Dingo\\Api\\Tests\\Stubs\\RoutingAdapterStub;\nuse Illuminate\\Container\\Container;\nuse Illuminate\\Routing\\Route as IlluminateRoute;\nuse Mockery as m;\nuse Symfony\\Component\\HttpKernel\\Exception\\UnauthorizedHttpException;\n\nclass AuthTest extends BaseTestCase\n{\n    /**\n     * @var Container\n     */\n    protected $container;\n    /**\n     * @var RoutingAdapterStub\n     */\n    protected $adapter;\n    /**\n     * @var Router|m\\LegacyMockInterface|m\\MockInterface\n     */\n    protected $router;\n    /**\n     * @var Auth|m\\LegacyMockInterface|m\\MockInterface\n     */\n    protected $auth;\n    /**\n     * @var AuthMiddleware\n     */\n    protected $middleware;\n\n    public function setUp(): void\n    {\n        $this->container = new Container;\n        $this->adapter = new RoutingAdapterStub;\n        $this->router = m::mock(Router::class);\n        $this->auth = m::mock(Auth::class);\n        $this->middleware = new AuthMiddleware($this->router, $this->auth);\n    }\n\n    public function testProtectedRouteFiresAuthenticationAndPasses()\n    {\n        $request = Request::create('test', 'GET');\n\n        $route = new Route($this->adapter, $this->container, $request, new IlluminateRoute('GET', '/test', [\n            'providers' => [],\n        ]));\n\n        $this->auth->shouldReceive('check')->once()->with(false)->andReturn(false);\n        $this->auth->shouldReceive('authenticate')->once()->with([])->andReturn(null);\n\n        $this->router->shouldReceive('getCurrentRoute')->once()->andReturn($route);\n\n        $this->middleware->handle($request, function ($handledRequest) use ($request) {\n            $this->assertSame($handledRequest, $request);\n        });\n    }\n\n    public function testProtectedRouteAlreadyLoggedIn()\n    {\n        $request = Request::create('test', 'GET');\n\n        $route = new Route($this->adapter, $this->container, $request, new IlluminateRoute('GET', '/test', [\n            'providers' => [],\n        ]));\n\n        $this->auth->shouldReceive('check')->once()->with(false)->andReturn(true);\n\n        $this->router->shouldReceive('getCurrentRoute')->once()->andReturn($route);\n\n        $this->middleware->handle($request, function ($handledRequest) use ($request) {\n            $this->assertSame($handledRequest, $request);\n        });\n    }\n\n    public function testAuthenticationFailsAndExceptionIsThrown()\n    {\n        $this->expectException(UnauthorizedHttpException::class);\n\n        $exception = new UnauthorizedHttpException('test');\n\n        $request = Request::create('test', 'GET');\n\n        $route = new Route($this->adapter, $this->container, $request, new IlluminateRoute('GET', '/test', [\n            'providers' => [],\n        ]));\n\n        $this->auth->shouldReceive('check')->once()->with(false)->andReturn(false);\n        $this->auth->shouldReceive('authenticate')->once()->with([])->andThrow($exception);\n\n        $this->router->shouldReceive('getCurrentRoute')->once()->andReturn($route);\n\n        $this->middleware->handle($request, function () {\n            //\n        });\n    }\n}\n"
  },
  {
    "path": "tests/Http/Middleware/RateLimitTest.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Tests\\Http\\Middleware;\n\nuse Dingo\\Api\\Exception\\RateLimitExceededException;\nuse Dingo\\Api\\Http\\InternalRequest;\nuse Dingo\\Api\\Http\\Middleware\\RateLimit;\nuse Dingo\\Api\\Http\\RateLimit\\Handler;\nuse Dingo\\Api\\Http\\Request;\nuse Dingo\\Api\\Http\\Response;\nuse Dingo\\Api\\Routing\\Route;\nuse Dingo\\Api\\Routing\\Router;\nuse Dingo\\Api\\Tests\\BaseTestCase;\nuse Dingo\\Api\\Tests\\Stubs\\ThrottleStub;\nuse Illuminate\\Cache\\CacheManager;\nuse Illuminate\\Container\\Container;\nuse Mockery as m;\nuse Symfony\\Component\\HttpKernel\\Exception\\HttpException;\n\nclass RateLimitTest extends BaseTestCase\n{\n    /**\n     * @var Container\n     */\n    protected $container;\n    /**\n     * @var Router|m\\LegacyMockInterface|m\\MockInterface\n     */\n    protected $router;\n    /**\n     * @var CacheManager\n     */\n    protected $cache;\n    /**\n     * @var Handler\n     */\n    protected $handler;\n    /**\n     * @var RateLimit\n     */\n    protected $middleware;\n\n    public function setUp(): void\n    {\n        $this->container = new Container;\n        $this->container['config'] = ['cache.default' => 'array', 'cache.stores.array' => ['driver' => 'array']];\n\n        $this->router = m::mock(Router::class);\n        $this->cache = new CacheManager($this->container);\n        $this->handler = new Handler($this->container, $this->cache, []);\n        $this->middleware = new RateLimit($this->router, $this->handler);\n\n        $this->handler->setRateLimiter(function ($container, $request) {\n            return $request->getClientIp();\n        });\n    }\n\n    public function testMiddlewareBypassesRequestsWithNoRateLimiting()\n    {\n        $request = Request::create('test', 'GET');\n\n        $route = m::mock(Route::class);\n        $route->shouldReceive('hasThrottle')->once()->andReturn(false);\n        $route->shouldReceive('getRateLimit')->once()->andReturn(0);\n        $route->shouldReceive('getRateLimitExpiration')->once()->andReturn(0);\n\n        $this->router->shouldReceive('getCurrentRoute')->once()->andReturn($route);\n\n        $this->handler->extend(new ThrottleStub([], false));\n\n        $response = $this->middleware->handle($request, function ($request) {\n            return new Response('foo');\n        });\n\n        $this->assertSame('foo', $response->getContent());\n        $this->assertArrayNotHasKey('x-ratelimit-limit', $response->headers->all());\n        $this->assertArrayNotHasKey('x-ratelimit-remaining', $response->headers->all());\n        $this->assertArrayNotHasKey('x-ratelimit-reset', $response->headers->all());\n    }\n\n    public function testMiddlewareBypassesInternalRequest()\n    {\n        $request = InternalRequest::create('test', 'GET');\n\n        $route = m::mock(Route::class);\n        $route->shouldReceive('hasThrottle')->never();\n        $route->shouldReceive('getRateLimit')->never();\n        $route->shouldReceive('getRateLimitExpiration')->never();\n\n        $this->router->shouldReceive('getCurrentRoute')->never();\n\n        $this->handler->extend(new ThrottleStub([], false));\n\n        $response = $this->middleware->handle($request, function ($request) {\n            return new Response('foo');\n        });\n\n        $this->assertSame('foo', $response->getContent());\n        $this->assertArrayNotHasKey('x-ratelimit-limit', $response->headers->all());\n        $this->assertArrayNotHasKey('x-ratelimit-remaining', $response->headers->all());\n        $this->assertArrayNotHasKey('x-ratelimit-reset', $response->headers->all());\n    }\n\n    public function testRateLimitingPassesAndResponseHeadersAreSet()\n    {\n        $request = Request::create('test', 'GET');\n\n        $route = m::mock(Route::class);\n        $route->shouldReceive('hasThrottle')->once()->andReturn(false);\n        $route->shouldReceive('getRateLimit')->once()->andReturn(0);\n        $route->shouldReceive('getRateLimitExpiration')->once()->andReturn(0);\n\n        $this->router->shouldReceive('getCurrentRoute')->once()->andReturn($route);\n\n        $this->handler->extend(new ThrottleStub(['limit' => 1]));\n\n        $response = $this->middleware->handle($request, function ($request) {\n            return new Response('foo');\n        });\n\n        $this->assertSame('foo', $response->getContent());\n        $this->assertArrayHasKey('x-ratelimit-limit', $response->headers->all());\n        $this->assertArrayHasKey('x-ratelimit-remaining', $response->headers->all());\n        $this->assertArrayHasKey('x-ratelimit-reset', $response->headers->all());\n    }\n\n    public function testRateLimitingFailsAndHeadersAreSetOnException()\n    {\n        $request = Request::create('test', 'GET');\n\n        $route = m::mock(Route::class);\n        $route->shouldReceive('hasThrottle')->once()->andReturn(false);\n        $route->shouldReceive('getRateLimit')->once()->andReturn(0);\n        $route->shouldReceive('getRateLimitExpiration')->once()->andReturn(0);\n\n        $this->router->shouldReceive('getCurrentRoute')->once()->andReturn($route);\n\n        $this->handler->extend(new ThrottleStub(['limit' => 0]));\n\n        try {\n            $this->middleware->handle($request, function ($request) {\n                return new Response('foo');\n            });\n        } catch (HttpException $exception) {\n            $this->assertInstanceOf(RateLimitExceededException::class, $exception);\n            $this->assertSame(429, $exception->getStatusCode());\n            $this->assertSame('You have exceeded your rate limit.', $exception->getMessage());\n\n            $headers = $exception->getHeaders();\n            $this->assertSame($headers['X-RateLimit-Reset'] - time(), $headers['Retry-After']);\n            $this->assertArrayHasKey('X-RateLimit-Limit', $headers);\n            $this->assertArrayHasKey('X-RateLimit-Remaining', $headers);\n            $this->assertArrayHasKey('X-RateLimit-Reset', $headers);\n        }\n    }\n\n    public function testRateLimitingWithLimitsSetOnRoute()\n    {\n        $request = Request::create('test', 'GET');\n\n        $route = m::mock(Route::class);\n        $route->shouldReceive('hasThrottle')->once()->andReturn(false);\n        $route->shouldReceive('getRateLimit')->once()->andReturn(5);\n        $route->shouldReceive('getRateLimitExpiration')->once()->andReturn(10);\n\n        $this->router->shouldReceive('getCurrentRoute')->once()->andReturn($route);\n\n        $response = $this->middleware->handle($request, function ($request) {\n            return new Response('foo');\n        });\n\n        $this->assertArrayHasKey('x-ratelimit-limit', $response->headers->all());\n        $this->assertArrayHasKey('x-ratelimit-remaining', $response->headers->all());\n        $this->assertArrayHasKey('x-ratelimit-reset', $response->headers->all());\n        $this->assertEquals(4, $response->headers->get('x-ratelimit-remaining'));\n        $this->assertEquals(5, $response->headers->get('x-ratelimit-limit'));\n    }\n\n    public function testRateLimitingWithRouteThrottle()\n    {\n        $request = Request::create('test', 'GET');\n\n        $route = m::mock(Route::class);\n        $route->shouldReceive('hasThrottle')->once()->andReturn(true);\n        $route->shouldReceive('getThrottle')->once()->andReturn(new ThrottleStub(['limit' => 10, 'expires' => 20]));\n        $route->shouldReceive('getRateLimit')->once()->andReturn(0);\n        $route->shouldReceive('getRateLimitExpiration')->once()->andReturn(0);\n\n        $this->router->shouldReceive('getCurrentRoute')->once()->andReturn($route);\n\n        $response = $this->middleware->handle($request, function ($request) {\n            return new Response('foo');\n        });\n\n        $this->assertArrayHasKey('x-ratelimit-limit', $response->headers->all());\n        $this->assertArrayHasKey('x-ratelimit-remaining', $response->headers->all());\n        $this->assertArrayHasKey('x-ratelimit-reset', $response->headers->all());\n        $this->assertEquals(9, $response->headers->get('x-ratelimit-remaining'));\n        $this->assertEquals(10, $response->headers->get('x-ratelimit-limit'));\n    }\n}\n"
  },
  {
    "path": "tests/Http/Middleware/RequestTest.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Tests\\Http\\Middleware;\n\nuse Dingo\\Api\\Contract\\Http\\Request as RequestContract;\nuse Dingo\\Api\\Exception\\Handler;\nuse Dingo\\Api\\Http\\Middleware\\Request as RequestMiddleware;\nuse Dingo\\Api\\Http\\Parser\\Accept as AcceptParser;\nuse Dingo\\Api\\Http\\Request;\nuse Dingo\\Api\\Http\\RequestValidator;\nuse Dingo\\Api\\Http\\Validation;\nuse Dingo\\Api\\Http\\Validation\\Accept;\nuse Dingo\\Api\\Http\\Validation\\Domain;\nuse Dingo\\Api\\Http\\Validation\\Prefix;\nuse Dingo\\Api\\Routing\\Router;\nuse Dingo\\Api\\Tests\\BaseTestCase;\nuse Dingo\\Api\\Tests\\ChecksLaravelVersionTrait;\nuse Illuminate\\Events\\Dispatcher as EventDispatcher;\nuse Illuminate\\Http\\Request as IlluminateRequest;\nuse Mockery as m;\n\nclass RequestTest extends BaseTestCase\n{\n    /**\n     * @var \\Dingo\\Api\\Tests\\Stubs\\Application58Stub|\\Dingo\\Api\\Tests\\Stubs\\Application6Stub|\\Dingo\\Api\\Tests\\Stubs\\ApplicationStub\n     */\n    protected $app;\n    /**\n     * @var Router|m\\LegacyMockInterface|m\\MockInterface\n     */\n    protected $router;\n    /**\n     * @var RequestValidator\n     */\n    protected $validator;\n    /**\n     * @var Handler|m\\LegacyMockInterface|m\\MockInterface\n     */\n    protected $handler;\n    /**\n     * @var EventDispatcher\n     */\n    protected $events;\n    /**\n     * @var RequestMiddleware\n     */\n    protected $middleware;\n\n    use ChecksLaravelVersionTrait;\n\n    public function setUp(): void\n    {\n        parent::setUp();\n\n        $this->app = $this->getApplicationStub();\n        $this->router = m::mock(Router::class);\n        $this->validator = new RequestValidator($this->app);\n        $this->handler = m::mock(Handler::class);\n        $this->events = new EventDispatcher($this->app);\n\n        $this->app->alias(Request::class, RequestContract::class);\n\n        $this->middleware = new RequestMiddleware($this->app, $this->handler, $this->router, $this->validator, $this->events);\n    }\n\n    public function testNoPrefixOrDomainDoesNotMatch()\n    {\n        $this->app[Domain::class] = new Validation\\Domain(null);\n        $this->app[Prefix::class] = new Validation\\Prefix(null);\n        $this->app[Accept::class] = new Validation\\Accept(new AcceptParser('vnd', 'api', 'v1', 'json'));\n\n        $request = Request::create('foo', 'GET');\n\n        $this->middleware->handle($request, function ($handled) use ($request) {\n            $this->assertSame($handled, $request);\n        });\n    }\n\n    public function testPrefixMatchesAndSendsRequestThroughRouter()\n    {\n        $this->app[Domain::class] = new Validation\\Domain(null);\n        $this->app[Prefix::class] = new Validation\\Prefix('/');\n        $this->app[Accept::class] = new Validation\\Accept(new AcceptParser('vnd', 'api', 'v1', 'json'));\n\n        $request = IlluminateRequest::create('foo', 'GET');\n\n        $this->router->shouldReceive('dispatch')->once();\n\n        $this->middleware->handle($request, function () {\n            //\n        });\n\n        $this->app[Domain::class] = new Validation\\Domain(null);\n        $this->app[Prefix::class] = new Validation\\Prefix('bar');\n        $this->app[Accept::class] = new Validation\\Accept(new AcceptParser('vnd', 'api', 'v1', 'json'));\n\n        $request = IlluminateRequest::create('bar/foo', 'GET');\n\n        $this->router->shouldReceive('dispatch')->once();\n\n        $this->middleware->handle($request, function () {\n            //\n        });\n\n        $request = IlluminateRequest::create('bing/bar/foo', 'GET');\n\n        $this->middleware->handle($request, function ($handled) use ($request) {\n            $this->assertSame($handled, $request);\n        });\n    }\n\n    public function testDomainMatchesAndSendsRequestThroughRouter()\n    {\n        $this->app[Domain::class] = new Validation\\Domain('foo.bar');\n        $this->app[Prefix::class] = new Validation\\Prefix(null);\n        $this->app[Accept::class] = new Validation\\Accept(new AcceptParser('vnd', 'api', 'v1', 'json'));\n\n        $request = IlluminateRequest::create('http://foo.bar/baz', 'GET');\n\n        $this->router->shouldReceive('dispatch')->once();\n\n        $this->middleware->handle($request, function () {\n            //\n        });\n\n        $request = IlluminateRequest::create('http://bing.foo.bar/baz', 'GET');\n\n        $this->middleware->handle($request, function ($handled) use ($request) {\n            $this->assertSame($handled, $request);\n        });\n    }\n}\n"
  },
  {
    "path": "tests/Http/Parser/AcceptTest.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Tests\\Http\\Parser;\n\nuse Dingo\\Api\\Http\\Parser\\Accept;\nuse Dingo\\Api\\Http\\Request;\nuse Dingo\\Api\\Tests\\BaseTestCase;\nuse Symfony\\Component\\HttpKernel\\Exception\\BadRequestHttpException;\n\nclass AcceptTest extends BaseTestCase\n{\n    public function testParsingInvalidAcceptReturnsDefaults()\n    {\n        $parser = new Accept('vnd', 'api', 'v1', 'json');\n\n        $accept = $parser->parse($this->createRequest('foo', 'GET', ['accept' => 'application/vnd.foo.v2+xml']));\n\n        $this->assertSame('api', $accept['subtype']);\n        $this->assertSame('v1', $accept['version']);\n        $this->assertSame('json', $accept['format']);\n    }\n\n    public function testStrictlyParsingInvalidAcceptHeaderThrowsException()\n    {\n        $this->expectException(BadRequestHttpException::class);\n        $this->expectExceptionMessage('Accept header could not be properly parsed because of a strict matching process.');\n\n        $parser = new Accept('vnd', 'api', 'v1', 'json');\n\n        $parser->parse($this->createRequest('foo', 'GET', ['accept' => 'application/vnd.foo.v2+xml']), true);\n    }\n\n    public function testParsingValidAcceptReturnsHeaderValues()\n    {\n        $parser = new Accept('vnd', 'api', 'v1', 'json');\n\n        $accept = $parser->parse($this->createRequest('foo', 'GET', ['accept' => 'application/vnd.api.v2+xml']));\n\n        $this->assertSame('api', $accept['subtype']);\n        $this->assertSame('v2', $accept['version']);\n        $this->assertSame('xml', $accept['format']);\n    }\n\n    public function testApiVersionWithoutVSuffix()\n    {\n        $parser = new Accept('vnd', 'api', '1.0', 'json');\n\n        $accept = $parser->parse($this->createRequest('foo', 'GET', ['accept' => 'application/vnd.api.1.0+xml']));\n\n        $this->assertSame('api', $accept['subtype']);\n        $this->assertSame('1.0', $accept['version']);\n        $this->assertSame('xml', $accept['format']);\n    }\n\n    public function testApiVersionWithHyphen()\n    {\n        $parser = new Accept('vnd', 'api', '1.0-beta', 'json');\n\n        $accept = $parser->parse($this->createRequest('foo', 'GET', ['accept' => 'application/vnd.api.1.0-beta+xml']));\n\n        $this->assertSame('api', $accept['subtype']);\n        $this->assertSame('1.0-beta', $accept['version']);\n        $this->assertSame('xml', $accept['format']);\n    }\n\n    protected function createRequest($uri, $method, array $headers = [])\n    {\n        $request = Request::create($uri, $method);\n\n        foreach ($headers as $key => $value) {\n            $request->headers->set($key, $value);\n        }\n\n        return $request;\n    }\n}\n"
  },
  {
    "path": "tests/Http/RateLimit/HandlerTest.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Tests\\Http\\RateLimit;\n\nuse Dingo\\Api\\Http\\RateLimit\\Handler;\nuse Dingo\\Api\\Http\\RateLimit\\Throttle\\Route;\nuse Dingo\\Api\\Http\\Request;\nuse Dingo\\Api\\Tests\\BaseTestCase;\nuse Dingo\\Api\\Tests\\Stubs\\ThrottleStub;\nuse Illuminate\\Cache\\CacheManager;\nuse Illuminate\\Container\\Container;\n\nclass HandlerTest extends BaseTestCase\n{\n    /**\n     * @var Container\n     */\n    protected $container;\n    /**\n     * @var CacheManager\n     */\n    protected $cache;\n    /**\n     * @var Handler\n     */\n    protected $limiter;\n\n    public function setUp(): void\n    {\n        $this->container = new Container;\n        $this->container['config'] = ['cache.default' => 'array', 'cache.stores.array' => ['driver' => 'array']];\n\n        $this->cache = new CacheManager($this->container);\n        $this->limiter = new Handler($this->container, $this->cache, []);\n\n        $this->limiter->setRateLimiter(function ($container, $request) {\n            return $request->getClientIp();\n        });\n    }\n\n    public function testSettingSpecificLimitsOnRouteUsesRouteSpecificThrottle()\n    {\n        $this->limiter->rateLimitRequest(Request::create('test', 'GET'), 100, 100);\n\n        $throttle = $this->limiter->getThrottle();\n\n        $this->assertInstanceOf(Route::class, $throttle);\n        $this->assertSame(100, $throttle->getLimit());\n        $this->assertSame(100, $throttle->getExpires());\n    }\n\n    public function testThrottleWithHighestAmountOfRequestsIsUsedWhenMoreThanOneMatchingThrottle()\n    {\n        $this->limiter->extend($first = new ThrottleStub(['limit' => 100, 'expires' => 200]));\n        $this->limiter->extend($second = new ThrottleStub(['limit' => 99, 'expires' => 400]));\n\n        $this->limiter->rateLimitRequest(Request::create('test', 'GET'));\n\n        $this->assertSame($first, $this->limiter->getThrottle());\n    }\n\n    public function testExceedingOfRateLimit()\n    {\n        $request = Request::create('test', 'GET');\n\n        $this->limiter->rateLimitRequest($request);\n        $this->assertFalse($this->limiter->exceededRateLimit());\n\n        $this->limiter->extend(new ThrottleStub(['limit' => 1, 'expires' => 200]));\n        $this->limiter->rateLimitRequest($request);\n        $this->assertFalse($this->limiter->exceededRateLimit());\n\n        $this->limiter->rateLimitRequest($request);\n        $this->assertTrue($this->limiter->exceededRateLimit());\n    }\n\n    public function testGettingTheRemainingLimit()\n    {\n        $this->limiter->extend(new ThrottleStub(['limit' => 10, 'expires' => 200]));\n        $this->limiter->rateLimitRequest(Request::create('test', 'GET'));\n        $this->assertSame(9, $this->limiter->getRemainingLimit());\n    }\n}\n"
  },
  {
    "path": "tests/Http/RateLimit/Throttle/AuthenticatedTest.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Tests\\Http\\RateLimit\\Throttle;\n\nuse Dingo\\Api\\Auth\\Auth;\nuse Dingo\\Api\\Http\\RateLimit\\Throttle\\Authenticated;\nuse Dingo\\Api\\Tests\\BaseTestCase;\nuse Illuminate\\Container\\Container;\nuse Mockery;\n\nclass AuthenticatedTest extends BaseTestCase\n{\n    public function testThrottleMatchesCorrectly()\n    {\n        $auth = Mockery::mock(Auth::class)->shouldReceive('check')->once()->andReturn(true)->getMock();\n        $container = new Container;\n        $container['api.auth'] = $auth;\n\n        $this->assertTrue((new Authenticated)->match($container));\n    }\n}\n"
  },
  {
    "path": "tests/Http/RateLimit/Throttle/UnauthenticatedTest.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Tests\\Http\\RateLimit\\Throttle;\n\nuse Dingo\\Api\\Auth\\Auth;\nuse Dingo\\Api\\Http\\RateLimit\\Throttle\\Unauthenticated;\nuse Dingo\\Api\\Tests\\BaseTestCase;\nuse Illuminate\\Container\\Container;\nuse Mockery;\n\nclass UnauthenticatedTest extends BaseTestCase\n{\n    public function testThrottleMatchesCorrectly()\n    {\n        $auth = Mockery::mock(Auth::class)->shouldReceive('check')->once()->andReturn(true)->getMock();\n        $container = new Container;\n        $container['api.auth'] = $auth;\n\n        $this->assertFalse((new Unauthenticated)->match($container));\n    }\n}\n"
  },
  {
    "path": "tests/Http/RequestValidatorTest.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Tests\\Http;\n\nuse Dingo\\Api\\Http\\Parser\\Accept as AcceptParser;\nuse Dingo\\Api\\Http\\RequestValidator;\nuse Dingo\\Api\\Tests\\BaseTestCase;\nuse Dingo\\Api\\Tests\\Stubs\\HttpValidatorStub;\nuse Illuminate\\Container\\Container;\nuse Illuminate\\Http\\Request;\n\nclass RequestValidatorTest extends BaseTestCase\n{\n    /**\n     * @var Container\n     */\n    protected $container;\n    /**\n     * @var RequestValidator\n     */\n    protected $validator;\n\n    public function setUp(): void\n    {\n        $this->container = new Container;\n        $this->container->instance(AcceptParser::class, new AcceptParser('vnd', 'test', 'v1', 'json'));\n        $this->validator = new RequestValidator($this->container);\n    }\n\n    public function testValidationFailsWithNoValidators()\n    {\n        $this->validator->replace([]);\n\n        $this->assertFalse($this->validator->validateRequest(Request::create('foo', 'GET')), 'Validation passed when there were no validators.');\n    }\n\n    public function testValidationFails()\n    {\n        $this->validator->replace([HttpValidatorStub::class]);\n\n        $this->assertFalse($this->validator->validateRequest(Request::create('foo', 'GET')), 'Validation passed when given a GET request.');\n    }\n\n    public function testValidationPasses()\n    {\n        $this->validator->replace([HttpValidatorStub::class]);\n\n        $this->assertTrue($this->validator->validateRequest(Request::create('foo', 'POST')), 'Validation failed when given a POST request.');\n    }\n}\n"
  },
  {
    "path": "tests/Http/Response/FactoryTest.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Tests\\Http\\Response;\n\nuse Closure;\nuse Dingo\\Api\\Http\\Response\\Factory;\nuse Dingo\\Api\\Tests\\BaseTestCase;\nuse Dingo\\Api\\Tests\\Stubs\\UserStub;\nuse Dingo\\Api\\Transformer\\Factory as TransformerFactory;\nuse Illuminate\\Pagination\\Paginator;\nuse Illuminate\\Support\\Collection;\nuse League\\Fractal\\Manager;\nuse League\\Fractal\\Resource\\Item;\nuse Mockery;\nuse Symfony\\Component\\HttpKernel\\Exception\\HttpException;\n\nclass FactoryTest extends BaseTestCase\n{\n    /**\n     * @var TransformerFactory|Mockery\\LegacyMockInterface|Mockery\\MockInterface\n     */\n    protected $transformer;\n    /**\n     * @var Factory\n     */\n    protected $factory;\n\n    public function setUp(): void\n    {\n        $this->transformer = Mockery::mock(TransformerFactory::class);\n        $this->factory = new Factory($this->transformer);\n    }\n\n    public function testMakingACreatedResponse()\n    {\n        $response = $this->factory->created();\n        $responseWithLocation = $this->factory->created('test');\n\n        $this->assertSame($response->getStatusCode(), 201);\n        $this->assertFalse($response->headers->has('Location'));\n\n        $this->assertSame($responseWithLocation->getStatusCode(), 201);\n        $this->assertTrue($responseWithLocation->headers->has('Location'));\n        $this->assertSame($responseWithLocation->headers->get('Location'), 'test');\n    }\n\n    public function testMakingAnAcceptedResponse()\n    {\n        $response = $this->factory->accepted();\n        $responseWithLocation = $this->factory->accepted('testHeader');\n        $responseWithContent = $this->factory->accepted(null, 'testContent');\n        $responseWithBoth = $this->factory->accepted('testHeader', 'testContent');\n\n        $this->assertSame($response->getStatusCode(), 202);\n        $this->assertFalse($response->headers->has('Location'));\n        $this->assertSame('', $response->getContent());\n\n        $this->assertSame($responseWithLocation->getStatusCode(), 202);\n        $this->assertTrue($responseWithLocation->headers->has('Location'));\n        $this->assertSame($responseWithLocation->headers->get('Location'), 'testHeader');\n        $this->assertSame('', $responseWithLocation->getContent());\n\n        $this->assertSame($responseWithContent->getStatusCode(), 202);\n        $this->assertFalse($responseWithContent->headers->has('Location'));\n        $this->assertSame('testContent', $responseWithContent->getContent());\n\n        $this->assertSame($responseWithBoth->getStatusCode(), 202);\n        $this->assertTrue($responseWithBoth->headers->has('Location'));\n        $this->assertSame($responseWithBoth->headers->get('Location'), 'testHeader');\n        $this->assertSame('testContent', $responseWithBoth->getContent());\n    }\n\n    public function testMakingANoContentResponse()\n    {\n        $response = $this->factory->noContent();\n        $this->assertSame(204, $response->getStatusCode());\n        $this->assertSame('', $response->getContent());\n        $this->assertNull($response->headers->get('Content-Type'));\n    }\n\n    public function testMakingCollectionRegistersUnderlyingClassWithTransformer()\n    {\n        $this->transformer->shouldReceive('register')->twice()->with(UserStub::class, 'test', [], null);\n\n        $this->assertInstanceOf(Collection::class, $this->factory->collection(new Collection([new UserStub('Jason')]), 'test')->getOriginalContent());\n        $this->assertInstanceOf(Collection::class, $this->factory->withCollection(new Collection([new UserStub('Jason')]), 'test')->getOriginalContent());\n    }\n\n    public function testMakingCollectionResponseWithThreeParameters()\n    {\n        $this->transformer->shouldReceive('register')->twice()->with(UserStub::class, 'test', [], Mockery::on(function ($param) {\n            return $param instanceof Closure;\n        }));\n\n        $this->assertInstanceOf(Collection::class, $this->factory->collection(new Collection([new UserStub('Jason')]), 'test', function ($resource, $fractal) {\n            $this->assertInstanceOf(\\League\\Fractal\\Resource\\Collection::class, $resource);\n            $this->assertInstanceOf(Manager::class, $fractal);\n        })->getOriginalContent());\n        $this->assertInstanceOf(Collection::class, $this->factory->withCollection(new Collection([new UserStub('Jason')]), 'test', function ($resource, $fractal) {\n            $this->assertInstanceOf(\\League\\Fractal\\Resource\\Collection::class, $resource);\n            $this->assertInstanceOf(Manager::class, $fractal);\n        })->getOriginalContent());\n    }\n\n    public function testMakingItemsRegistersClassWithTransformer()\n    {\n        $this->transformer->shouldReceive('register')->twice()->with(UserStub::class, 'test', [], null);\n\n        $this->assertInstanceOf(UserStub::class, $this->factory->item(new UserStub('Jason'), 'test')->getOriginalContent());\n        $this->assertInstanceOf(UserStub::class, $this->factory->withItem(new UserStub('Jason'), 'test')->getOriginalContent());\n    }\n\n    public function testMakingItemResponseWithThreeParameters()\n    {\n        $this->transformer->shouldReceive('register')->twice()->with(UserStub::class, 'test', [], Mockery::on(function ($param) {\n            return $param instanceof Closure;\n        }));\n\n        $this->assertInstanceOf(UserStub::class, $this->factory->item(new UserStub('Jason'), 'test', function ($resource, $fractal) {\n            $this->assertInstanceOf(Item::class, $resource);\n            $this->assertInstanceOf(Manager::class, $fractal);\n        })->getOriginalContent());\n        $this->assertInstanceOf(UserStub::class, $this->factory->withItem(new UserStub('Jason'), 'test', function ($resource, $fractal) {\n            $this->assertInstanceOf(Item::class, $resource);\n            $this->assertInstanceOf(Manager::class, $fractal);\n        })->getOriginalContent());\n    }\n\n    public function testMakingPaginatorRegistersUnderlyingClassWithTransformer()\n    {\n        $this->transformer->shouldReceive('register')->twice()->with(UserStub::class, 'test', [], null);\n\n        $this->assertInstanceOf(Paginator::class, $this->factory->paginator(new Paginator([new UserStub('Jason')], 1), 'test')->getOriginalContent());\n        $this->assertInstanceOf(Paginator::class, $this->factory->withPaginator(new Paginator([new UserStub('Jason')], 1), 'test')->getOriginalContent());\n    }\n\n    public function testNotFoundThrowsHttpException()\n    {\n        $this->expectException(HttpException::class);\n\n        $this->factory->errorNotFound();\n    }\n\n    public function testBadRequestThrowsHttpException()\n    {\n        $this->expectException(HttpException::class);\n\n        $this->factory->errorBadRequest();\n    }\n\n    public function testForbiddenThrowsHttpException()\n    {\n        $this->expectException(HttpException::class);\n\n        $this->factory->errorForbidden();\n    }\n\n    public function testInternalThrowsHttpException()\n    {\n        $this->expectException(HttpException::class);\n\n        $this->factory->errorInternal();\n    }\n\n    public function testUnauthorizedThrowsHttpException()\n    {\n        $this->expectException(HttpException::class);\n\n        $this->factory->errorUnauthorized();\n    }\n\n    public function testMethodNotAllowedThrowsHttpException()\n    {\n        $this->expectException(HttpException::class);\n\n        $this->factory->errorMethodNotAllowed();\n    }\n\n    public function testMakingArrayResponse()\n    {\n        $response = $this->factory->array(['foo' => 'bar']);\n        $this->assertSame('{\"foo\":\"bar\"}', $response->getContent());\n    }\n\n    public function testPrefixingWithCallsMethodsCorrectly()\n    {\n        $response = $this->factory->withArray(['foo' => 'bar']);\n        $this->assertSame('{\"foo\":\"bar\"}', $response->getContent());\n    }\n}\n"
  },
  {
    "path": "tests/Http/Response/Format/ExpectedPrettyPrintedJson/testMorphingArrayWithEightSpacesPrettyPrintIndent.json.php",
    "content": "<?php\n\n/*\n * Pretty printed JSON with 8 spaces indent\n *\n * @return string\n */\n\nreturn <<<'JSON'\n{\n        \"foo\": \"bar\",\n        \"baz\": {\n                \"foobar\": [\n                        42,\n                        0.00042,\n                        \"\",\n                        null\n                ]\n        }\n}\nJSON;\n"
  },
  {
    "path": "tests/Http/Response/Format/ExpectedPrettyPrintedJson/testMorphingArrayWithFourSpacesPrettyPrintIndent.json.php",
    "content": "<?php\n\n/*\n * Pretty printed JSON with 4 spaces indent\n *\n * @return string\n */\n\nreturn <<<'JSON'\n{\n    \"foo\": \"bar\",\n    \"baz\": {\n        \"foobar\": [\n            42,\n            0.00042,\n            \"\",\n            null\n        ]\n    }\n}\nJSON;\n"
  },
  {
    "path": "tests/Http/Response/Format/ExpectedPrettyPrintedJson/testMorphingArrayWithOneTabPrettyPrintIndent.json.php",
    "content": "<?php\n\n/*\n * Pretty printed with one tab indent\n *\n * @return string\n */\n\nreturn <<<'JSON'\n{\n\t\"foo\": \"bar\",\n\t\"baz\": {\n\t\t\"foobar\": [\n\t\t\t42,\n\t\t\t0.00042,\n\t\t\t\"\",\n\t\t\tnull\n\t\t]\n\t}\n}\nJSON;\n"
  },
  {
    "path": "tests/Http/Response/Format/ExpectedPrettyPrintedJson/testMorphingArrayWithTwoSpacesPrettyPrintIndent.json.php",
    "content": "<?php\n\n/*\n * Pretty printed JSON with 2 spaces indent\n *\n * @return string\n */\n\nreturn <<<'JSON'\n{\n  \"foo\": \"bar\",\n  \"baz\": {\n    \"foobar\": [\n      42,\n      0.00042,\n      \"\",\n      null\n    ]\n  }\n}\nJSON;\n"
  },
  {
    "path": "tests/Http/Response/Format/ExpectedPrettyPrintedJsonp/testMorphingArrayWithEightSpacesPrettyPrintIndent.jsonp.php",
    "content": "<?php\n\n/*\n * Pretty printed JSON with 8 spaces indent\n *\n * @return string\n */\n\nreturn <<<'JSON'\nfoo({\n        \"foo\": \"bar\",\n        \"baz\": {\n                \"foobar\": [\n                        42,\n                        0.00042,\n                        \"\",\n                        null\n                ]\n        }\n});\nJSON;\n"
  },
  {
    "path": "tests/Http/Response/Format/ExpectedPrettyPrintedJsonp/testMorphingArrayWithFourSpacesPrettyPrintIndent.jsonp.php",
    "content": "<?php\n\n/*\n * Pretty printed JSONP with 4 spaces indent\n *\n * @return string\n */\n\nreturn <<<'JSON'\nfoo({\n    \"foo\": \"bar\",\n    \"baz\": {\n        \"foobar\": [\n            42,\n            0.00042,\n            \"\",\n            null\n        ]\n    }\n});\nJSON;\n"
  },
  {
    "path": "tests/Http/Response/Format/ExpectedPrettyPrintedJsonp/testMorphingArrayWithOneTabPrettyPrintIndent.jsonp.php",
    "content": "<?php\n\n/*\n * Pretty printed JSONP with one tab indent\n *\n * @return string\n */\n\nreturn <<<'JSON'\nfoo({\n\t\"foo\": \"bar\",\n\t\"baz\": {\n\t\t\"foobar\": [\n\t\t\t42,\n\t\t\t0.00042,\n\t\t\t\"\",\n\t\t\tnull\n\t\t]\n\t}\n});\nJSON;\n"
  },
  {
    "path": "tests/Http/Response/Format/ExpectedPrettyPrintedJsonp/testMorphingArrayWithTwoSpacesPrettyPrintIndent.jsonp.php",
    "content": "<?php\n\n/*\n * Pretty printed JSONP with 2 spaces indent\n *\n * @return string\n */\n\nreturn <<<'JSON'\nfoo({\n  \"foo\": \"bar\",\n  \"baz\": {\n    \"foobar\": [\n      42,\n      0.00042,\n      \"\",\n      null\n    ]\n  }\n});\nJSON;\n"
  },
  {
    "path": "tests/Http/Response/Format/JsonTest.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Tests\\Http\\Response\\Format;\n\nuse Dingo\\Api\\Http\\Response;\nuse Dingo\\Api\\Http\\Response\\Format\\Json;\nuse Dingo\\Api\\Tests\\BaseTestCase;\nuse Dingo\\Api\\Tests\\Stubs\\EloquentModelStub;\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Illuminate\\Support\\MessageBag;\n\nclass JsonTest extends BaseTestCase\n{\n    public function setUp(): void\n    {\n        Response::setFormatters(['json' => new Json]);\n    }\n\n    public function tearDown(): void\n    {\n        parent::tearDown();\n\n        EloquentModelStub::$snakeAttributes = true;\n    }\n\n    /*\n     * Read expected pretty printed JSON string from external file.\n     *\n     * JSON strings, that are expected for assertion in each test, are placed\n     * in separate files to avoid littering tests and available on demand.\n     * All the filenames are the same as the tests they associated to.\n     *\n     * @return string\n     */\n    private function getExpectedPrettyPrintedJson($testMethodName)\n    {\n        return require __DIR__.DIRECTORY_SEPARATOR.\n            'ExpectedPrettyPrintedJson'.DIRECTORY_SEPARATOR.\n            $testMethodName.'.json.php';\n    }\n\n    public function testMorphingEloquentModel()\n    {\n        $response = (new Response(new EloquentModelStub))->morph();\n\n        $this->assertSame('{\"foo_bar\":{\"foo\":\"bar\"}}', $response->getContent());\n    }\n\n    public function testMorphingEloquentCollection()\n    {\n        $response = (new Response(new Collection([new EloquentModelStub, new EloquentModelStub])))->morph();\n\n        $this->assertSame('{\"foo_bars\":[{\"foo\":\"bar\"},{\"foo\":\"bar\"}]}', $response->getContent());\n    }\n\n    public function testMorphingEmptyEloquentCollection()\n    {\n        $response = (new Response(new Collection))->morph();\n\n        $this->assertSame('[]', $response->getContent());\n    }\n\n    public function testMorphingString()\n    {\n        $response = (new Response('foo'))->morph();\n\n        $this->assertSame('foo', $response->getContent());\n    }\n\n    public function testMorphingArray()\n    {\n        $messages = new MessageBag(['foo' => 'bar']);\n\n        $response = (new Response(['foo' => 'bar', 'baz' => $messages]))->morph();\n\n        $this->assertSame('{\"foo\":\"bar\",\"baz\":{\"foo\":[\"bar\"]}}', $response->getContent());\n    }\n\n    public function testMorphingUnknownType()\n    {\n        $this->assertSame(1, (new Response(1))->morph()->getContent());\n    }\n\n    public function testMorphingEloquentModelWithCamelCasing()\n    {\n        EloquentModelStub::$snakeAttributes = false;\n\n        $response = (new Response(new EloquentModelStub))->morph();\n\n        $this->assertSame('{\"fooBar\":{\"foo\":\"bar\"}}', $response->getContent());\n    }\n\n    public function testMorphingEloquentCollectionWithCamelCasing()\n    {\n        EloquentModelStub::$snakeAttributes = false;\n\n        $response = (new Response(new Collection([new EloquentModelStub, new EloquentModelStub])))->morph();\n\n        $this->assertSame('{\"fooBars\":[{\"foo\":\"bar\"},{\"foo\":\"bar\"}]}', $response->getContent());\n    }\n\n    public function testMorphingArrayWithTwoSpacesPrettyPrintIndent()\n    {\n        $options = [\n            'json' => [\n                'pretty_print' => true,\n                'indent_style' => 'space',\n                'indent_size' => 2,\n            ],\n        ];\n\n        Response::setFormatsOptions($options);\n\n        $array = ['foo' => 'bar', 'baz' => ['foobar' => [42, 0.00042, '', null]]];\n\n        $response = (new Response($array))->morph();\n\n        $this->assertSame($this->getExpectedPrettyPrintedJson(__FUNCTION__), $response->getContent());\n    }\n\n    public function testMorphingArrayWithFourSpacesPrettyPrintIndent()\n    {\n        $options = [\n            'json' => [\n                'pretty_print' => true,\n                'indent_style' => 'space',\n                'indent_size' => 4,\n            ],\n        ];\n\n        Response::setFormatsOptions($options);\n\n        $array = ['foo' => 'bar', 'baz' => ['foobar' => [42, 0.00042, '', null]]];\n\n        $response = (new Response($array))->morph();\n\n        $this->assertSame($this->getExpectedPrettyPrintedJson(__FUNCTION__), $response->getContent());\n    }\n\n    public function testMorphingArrayWithEightSpacesPrettyPrintIndent()\n    {\n        $options = [\n            'json' => [\n                'pretty_print' => true,\n                'indent_style' => 'space',\n                'indent_size' => 8,\n            ],\n        ];\n\n        Response::setFormatsOptions($options);\n\n        $array = ['foo' => 'bar', 'baz' => ['foobar' => [42, 0.00042, '', null]]];\n\n        $response = (new Response($array))->morph();\n\n        $this->assertSame($this->getExpectedPrettyPrintedJson(__FUNCTION__), $response->getContent());\n    }\n\n    public function testMorphingArrayWithOneTabPrettyPrintIndent()\n    {\n        $options = [\n            'json' => [\n                'pretty_print' => true,\n                'indent_style' => 'tab',\n            ],\n        ];\n\n        Response::setFormatsOptions($options);\n\n        $array = ['foo' => 'bar', 'baz' => ['foobar' => [42, 0.00042, '', null]]];\n        $response = (new Response($array))->morph();\n\n        $this->assertSame($this->getExpectedPrettyPrintedJson(__FUNCTION__), $response->getContent());\n    }\n}\n"
  },
  {
    "path": "tests/Http/Response/Format/JsonpTest.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Tests\\Http\\Response\\Format;\n\nuse Dingo\\Api\\Http\\Response;\nuse Dingo\\Api\\Http\\Response\\Format\\Jsonp;\nuse Dingo\\Api\\Tests\\BaseTestCase;\nuse Dingo\\Api\\Tests\\Stubs\\EloquentModelStub;\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Support\\MessageBag;\n\nclass JsonpTest extends BaseTestCase\n{\n    public function setUp(): void\n    {\n        $formatter = new Jsonp;\n        $formatter->setRequest(Request::create('GET', '/', ['callback' => 'foo']));\n\n        Response::setFormatters(['json' => $formatter]);\n    }\n\n    /*\n     * Read expected pretty printed JSONP string from external file.\n     *\n     * JSONP strings, that are expected for assertion in each test, are placed\n     * in separate files to avoid littering tests and available on demand.\n     * All the filenames are the same as the tests they associated to.\n     *\n     * @return string\n     */\n    private function getExpectedPrettyPrintedJsonp($testMethodName)\n    {\n        return require __DIR__.DIRECTORY_SEPARATOR.\n            'ExpectedPrettyPrintedJsonp'.DIRECTORY_SEPARATOR.\n            $testMethodName.'.jsonp.php';\n    }\n\n    public function testMorphingEloquentModel()\n    {\n        $response = (new Response(new EloquentModelStub))->morph();\n\n        $this->assertSame('foo({\"foo_bar\":{\"foo\":\"bar\"}});', $response->getContent());\n    }\n\n    public function testMorphingEloquentCollection()\n    {\n        $response = (new Response(new Collection([new EloquentModelStub, new EloquentModelStub])))->morph();\n\n        $this->assertSame('foo({\"foo_bars\":[{\"foo\":\"bar\"},{\"foo\":\"bar\"}]});', $response->getContent());\n    }\n\n    public function testMorphingEmptyEloquentCollection()\n    {\n        $response = (new Response(new Collection))->morph();\n\n        $this->assertSame('foo([]);', $response->getContent());\n    }\n\n    public function testMorphingString()\n    {\n        $response = (new Response('foo'))->morph();\n\n        $this->assertSame('foo', $response->getContent());\n    }\n\n    public function testMorphingArray()\n    {\n        $messages = new MessageBag(['foo' => 'bar']);\n\n        $response = (new Response(['foo' => 'bar', 'baz' => $messages]))->morph();\n\n        $this->assertSame('foo({\"foo\":\"bar\",\"baz\":{\"foo\":[\"bar\"]}});', $response->getContent());\n    }\n\n    public function testMorphingUnknownType()\n    {\n        $this->assertSame(1, (new Response(1))->morph()->getContent());\n    }\n\n    public function testMorphingArrayWithOneTabPrettyPrintIndent()\n    {\n        $options = [\n            'json' => [\n                'pretty_print' => true,\n                'indent_style' => 'tab',\n            ],\n        ];\n\n        Response::setFormatsOptions($options);\n\n        $array = ['foo' => 'bar', 'baz' => ['foobar' => [42, 0.00042, '', null]]];\n        $response = (new Response($array))->morph();\n\n        $this->assertSame($this->getExpectedPrettyPrintedJsonp(__FUNCTION__), $response->getContent());\n    }\n\n    public function testMorphingArrayWithTwoSpacesPrettyPrintIndent()\n    {\n        $options = [\n            'json' => [\n                'pretty_print' => true,\n                'indent_style' => 'space',\n                'indent_size' => 2,\n            ],\n        ];\n\n        Response::setFormatsOptions($options);\n\n        $array = ['foo' => 'bar', 'baz' => ['foobar' => [42, 0.00042, '', null]]];\n        $response = (new Response($array))->morph();\n\n        $this->assertSame($this->getExpectedPrettyPrintedJsonp(__FUNCTION__), $response->getContent());\n    }\n\n    public function testMorphingArrayWithFourSpacesPrettyPrintIndent()\n    {\n        $options = [\n            'json' => [\n                'pretty_print' => true,\n                'indent_style' => 'space',\n                'indent_size' => 4,\n            ],\n        ];\n\n        Response::setFormatsOptions($options);\n\n        $array = ['foo' => 'bar', 'baz' => ['foobar' => [42, 0.00042, '', null]]];\n        $response = (new Response($array))->morph();\n\n        $this->assertSame($this->getExpectedPrettyPrintedJsonp(__FUNCTION__), $response->getContent());\n    }\n\n    public function testMorphingArrayWithEightSpacesPrettyPrintIndent()\n    {\n        $options = [\n            'json' => [\n                'pretty_print' => true,\n                'indent_style' => 'space',\n                'indent_size' => 8,\n            ],\n        ];\n\n        Response::setFormatsOptions($options);\n\n        $array = ['foo' => 'bar', 'baz' => ['foobar' => [42, 0.00042, '', null]]];\n        $response = (new Response($array))->morph();\n\n        $this->assertSame($this->getExpectedPrettyPrintedJsonp(__FUNCTION__), $response->getContent());\n    }\n}\n"
  },
  {
    "path": "tests/Http/ResponseTest.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Tests\\Http;\n\nuse Dingo\\Api\\Event\\ResponseIsMorphing;\nuse Dingo\\Api\\Event\\ResponseWasMorphed;\nuse Dingo\\Api\\Http\\Response;\nuse Dingo\\Api\\Http\\Response\\Format\\Json;\nuse Dingo\\Api\\Tests\\BaseTestCase;\nuse Dingo\\Api\\Transformer\\Binding;\nuse Illuminate\\Container\\Container;\nuse Illuminate\\Events\\Dispatcher as EventDispatcher;\nuse Mockery as m;\nuse StdClass;\nuse Symfony\\Component\\HttpKernel\\Exception\\NotAcceptableHttpException;\n\nclass ResponseTest extends BaseTestCase\n{\n    /**\n     * @var EventDispatcher\n     */\n    protected $events;\n\n    public function setUp(): void\n    {\n        Response::setEventDispatcher($this->events = new EventDispatcher);\n    }\n\n    public function testGettingInvalidFormatterThrowsException()\n    {\n        $this->expectException(NotAcceptableHttpException::class);\n        $this->expectExceptionMessage('Unable to format response according to Accept header.');\n\n        Response::getFormatter('json');\n    }\n\n    public function testNonCastableObjectsSetAsOriginalContent()\n    {\n        $object = new StdClass;\n        $object->id = 'test';\n\n        $response = new Response($object);\n\n        $this->assertNull($response->getContent());\n        $this->assertSame($object, $response->getOriginalContent());\n    }\n\n    public function testAddingAndSettingMetaCallsUnderlyingTransformerBinding()\n    {\n        $binding = new Binding(m::mock(Container::class), 'foo');\n\n        $response = new Response('test', 200, [], $binding);\n        $response->setMeta(['foo' => 'bar']);\n        $response->meta('bing', 'bang');\n\n        $this->assertSame(['foo' => 'bar', 'bing' => 'bang'], $response->getMeta());\n    }\n\n    public function testBuildingWithCustomStatusCodeAndHeaders()\n    {\n        $response = new Response('test');\n        $response->statusCode(302);\n        $response->header('Foo', 'Bar');\n\n        $this->assertSame('Bar', $response->headers->get('Foo'));\n        $this->assertSame(302, $response->getStatusCode());\n    }\n\n    public function testChangingContentWithEvents()\n    {\n        $this->events->listen(ResponseWasMorphed::class, function ($event) {\n            $event->content['foo'] = 'bam!';\n        });\n\n        Response::addFormatter('json', new Json);\n\n        $response = new Response(['foo' => 'bar']);\n\n        $this->assertSame('{\"foo\":\"bam!\"}', $response->morph('json')->getContent());\n\n        $this->events->forget(ResponseWasMorphed::class);\n    }\n\n    public function testChangingResponseHeadersWithEvents()\n    {\n        $this->events->listen(ResponseIsMorphing::class, function ($event) {\n            $event->response->headers->set('x-foo', 'bar');\n        });\n\n        Response::addFormatter('json', new Json);\n\n        $response = new Response(['foo' => 'bar']);\n\n        $this->assertSame('bar', $response->morph('json')->headers->get('x-foo'));\n\n        $this->events->forget(ResponseIsMorphing::class);\n    }\n}\n"
  },
  {
    "path": "tests/Http/Validation/AcceptTest.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Tests\\Http\\Validation;\n\nuse Dingo\\Api\\Http\\Parser\\Accept as AcceptParser;\nuse Dingo\\Api\\Http\\Validation\\Accept as AcceptValidator;\nuse Dingo\\Api\\Tests\\BaseTestCase;\nuse Illuminate\\Http\\Request;\n\nclass AcceptTest extends BaseTestCase\n{\n    public function testValidationPassesForStrictModeAndOptionsRequests()\n    {\n        $parser = new AcceptParser('vnd', 'api', 'v1', 'json');\n        $validator = new AcceptValidator($parser, true);\n\n        $this->assertTrue($validator->validate(Request::create('bar', 'OPTIONS')), 'Validation failed when it should have passed with an options request.');\n    }\n}\n"
  },
  {
    "path": "tests/Http/Validation/DomainTest.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Tests\\Http\\Validation;\n\nuse Dingo\\Api\\Http\\Validation\\Domain;\nuse Dingo\\Api\\Tests\\BaseTestCase;\nuse Illuminate\\Http\\Request;\n\nclass DomainTest extends BaseTestCase\n{\n    public function testValidationFailsWithInvalidOrNullDomain()\n    {\n        $validator = new Domain('http://foo.bar');\n        $this->assertFalse($validator->validate(Request::create('http://bar.foo', 'GET')), 'Validation passed when it should have failed with an invalid domain.');\n\n        $validator = new Domain(null);\n        $this->assertFalse($validator->validate(Request::create('http://bar.foo', 'GET')), 'Validation passed when it should have failed with a null domain.');\n    }\n\n    public function testValidationPasses()\n    {\n        $validator = new Domain('http://foo.bar');\n        $this->assertTrue($validator->validate(Request::create('http://foo.bar', 'GET')), 'Validation failed when it should have passed with a valid domain.');\n    }\n\n    public function testValidationPassesWithDifferentProtocols()\n    {\n        $validator = new Domain('ftp://foo.bar');\n        $this->assertTrue($validator->validate(Request::create('http://foo.bar', 'GET')), 'Validation failed when it should have passed with a valid domain.');\n\n        $validator = new Domain('https://foo.bar');\n        $this->assertTrue($validator->validate(Request::create('http://foo.bar', 'GET')), 'Validation failed when it should have passed with a valid domain.');\n    }\n\n    public function testValidationPassesWithPortOnDomain()\n    {\n        $validator = new Domain('http://foo.bar:8888');\n        $this->assertTrue($validator->validate(Request::create('http://foo.bar', 'GET')), 'Validation failed when it should have passed with a valid domain.');\n    }\n\n    public function testValidationPassesWithPortOnRequest()\n    {\n        $validator = new Domain('http://foo.bar');\n        $this->assertTrue($validator->validate(Request::create('http://foo.bar:8888', 'GET')), 'Validation failed when it should have passed with a valid domain.');\n    }\n\n    public function testValidationPassesWithPortOnDomainAndRequest()\n    {\n        $validator = new Domain('http://foo.bar:8888');\n        $this->assertTrue($validator->validate(Request::create('http://foo.bar:8888', 'GET')), 'Validation failed when it should have passed with a valid domain.');\n    }\n}\n"
  },
  {
    "path": "tests/Http/Validation/PrefixTest.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Tests\\Http\\Validation;\n\nuse Dingo\\Api\\Http\\Validation\\Prefix;\nuse Dingo\\Api\\Tests\\BaseTestCase;\nuse Illuminate\\Http\\Request;\n\nclass PrefixTest extends BaseTestCase\n{\n    public function testValidationFailsWithInvalidOrNullPrefix()\n    {\n        $validator = new Prefix('foo');\n        $this->assertFalse($validator->validate(Request::create('bar', 'GET')), 'Validation passed when it should have failed with an invalid prefix.');\n\n        $validator = new Prefix(null);\n        $this->assertFalse($validator->validate(Request::create('foo', 'GET')), 'Validation passed when it should have failed with a null prefix.');\n    }\n\n    public function testValidationPasses()\n    {\n        $validator = new Prefix('foo');\n        $this->assertTrue($validator->validate(Request::create('foo', 'GET')), 'Validation failed when it should have passed with a valid prefix.');\n        $this->assertTrue($validator->validate(Request::create('foo/bar', 'GET')), 'Validation failed when it should have passed with a valid prefix.');\n    }\n\n    public function testValidationPassesWithHyphenatedPrefix()\n    {\n        $validator = new Prefix('web-api');\n        $this->assertTrue($validator->validate(Request::create('web-api', 'GET')), 'Validation failed when it should have passed with a valid prefix.');\n        $this->assertTrue($validator->validate(Request::create('web-api/bar', 'GET')), 'Validation failed when it should have passed with a valid prefix.');\n    }\n}\n"
  },
  {
    "path": "tests/Routing/Adapter/BaseAdapterTest.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Tests\\Routing\\Adapter;\n\nuse Dingo\\Api\\Exception\\Handler;\nuse Dingo\\Api\\Http;\nuse Dingo\\Api\\Routing\\Adapter\\Laravel;\nuse Dingo\\Api\\Routing\\Adapter\\Lumen;\nuse Dingo\\Api\\Routing\\Router;\nuse Dingo\\Api\\Tests\\BaseTestCase;\nuse Dingo\\Api\\Tests\\Stubs\\MiddlewareStub;\nuse Illuminate\\Contracts\\Container\\Container;\nuse Laravel\\Lumen\\Application;\nuse Mockery as m;\n\nabstract class BaseAdapterTest extends BaseTestCase\n{\n    /**\n     * @var Container|Application\n     */\n    protected $container;\n    /**\n     * @var Laravel|Lumen\n     */\n    protected $adapter;\n    /**\n     * @var Handler\n     */\n    protected $exception;\n    /**\n     * @var Router\n     */\n    protected $router;\n\n    public function setUp(): void\n    {\n        $this->container = $this->getContainerInstance();\n        $this->container['Illuminate\\Container\\Container'] = $this->container;\n        $this->container['api.auth'] = new MiddlewareStub;\n        $this->container['api.limiting'] = new MiddlewareStub;\n        $this->container['api.controllers'] = new MiddlewareStub;\n        $this->container['request'] = new Http\\Request;\n\n        Http\\Request::setAcceptParser(new Http\\Parser\\Accept('vnd', 'api', 'v1', 'json'));\n\n        $this->adapter = $this->getAdapterInstance();\n        $this->exception = m::mock(Handler::class);\n        $this->router = new Router($this->adapter, $this->exception, $this->container, null, null);\n        app()->instance(\\Illuminate\\Routing\\Router::class, $this->adapter, true);\n\n        Http\\Response::setFormatters(['json' => new Http\\Response\\Format\\Json]);\n    }\n\n    /**\n     * @return Container|Application\n     */\n    abstract public function getContainerInstance();\n\n    /**\n     * @return Laravel|Lumen\n     */\n    abstract public function getAdapterInstance();\n\n    protected function createRequest($uri, $method, array $headers = [])\n    {\n        $request = Http\\Request::create($uri, $method);\n\n        foreach ($headers as $key => $value) {\n            $request->headers->set($key, $value);\n        }\n\n        return $this->container['request'] = $request;\n    }\n\n    public function testBasicRouteVersions()\n    {\n        $this->router->version('v1', function () {\n            $this->router->get('foo', function () {\n                return 'foo';\n            });\n            $this->router->post('foo', function () {\n                return 'posted';\n            });\n            $this->router->patch('foo', function () {\n                return 'patched';\n            });\n            $this->router->delete('foo', function () {\n                return 'deleted';\n            });\n            $this->router->put('foo', function () {\n                return 'put';\n            });\n            $this->router->options('foo', function () {\n                return 'options';\n            });\n        });\n\n        $this->router->group(['version' => 'v2'], function () {\n            $this->router->get('foo', ['version' => 'v3', function () {\n                return 'bar';\n            }]);\n        });\n\n        $this->createRequest('/', 'GET');\n\n        $this->assertArrayHasKey('v1', $this->router->getRoutes(), 'No routes were registered for version 1.');\n        $this->assertArrayHasKey('v2', $this->router->getRoutes(), 'No routes were registered for version 2.');\n        $this->assertArrayHasKey('v3', $this->router->getRoutes(), 'No routes were registered for version 3.');\n\n        $request = $this->createRequest('/foo', 'GET', ['accept' => 'application/vnd.api.v1+json']);\n        $this->assertSame('foo', $this->router->dispatch($request)->getContent());\n\n        $request = $this->createRequest('/foo/', 'GET', ['accept' => 'application/vnd.api.v1+json']);\n        $this->assertSame('foo', $this->router->dispatch($request)->getContent(), 'Could not dispatch request with trailing slash.');\n\n        $request = $this->createRequest('/foo', 'GET', ['accept' => 'application/vnd.api.v2+json']);\n        $this->assertSame('bar', $this->router->dispatch($request)->getContent());\n\n        $request = $this->createRequest('/foo', 'GET', ['accept' => 'application/vnd.api.v3+json']);\n        $this->assertSame('bar', $this->router->dispatch($request)->getContent());\n\n        $request = $this->createRequest('/foo', 'POST', ['accept' => 'application/vnd.api.v1+json']);\n        $this->assertSame('posted', $this->router->dispatch($request)->getContent());\n\n        $request = $this->createRequest('/foo', 'PATCH', ['accept' => 'application/vnd.api.v1+json']);\n        $this->assertSame('patched', $this->router->dispatch($request)->getContent());\n\n        $request = $this->createRequest('/foo', 'DELETE', ['accept' => 'application/vnd.api.v1+json']);\n        $this->assertSame('deleted', $this->router->dispatch($request)->getContent());\n\n        $request = $this->createRequest('/foo', 'PUT', ['accept' => 'application/vnd.api.v1+json']);\n        $this->assertSame('put', $this->router->dispatch($request)->getContent());\n\n        $request = $this->createRequest('/foo', 'options', ['accept' => 'application/vnd.api.v1+json']);\n        $this->assertSame('options', $this->router->dispatch($request)->getContent());\n    }\n\n    public function testAdapterDispatchesRequestsThroughRouter()\n    {\n        $this->container['request'] = Http\\Request::create('/foo', 'GET');\n\n        $this->router->version('v1', function () {\n            $this->router->get('foo', function () {\n                return 'foo';\n            });\n        });\n\n        $response = $this->router->dispatch($this->container['request']);\n\n        $this->assertSame('foo', $response->getContent());\n    }\n\n    public function testRoutesWithPrefix()\n    {\n        $this->router->version('v1', ['prefix' => 'foo/bar'], function () {\n            $this->router->get('foo', function () {\n                return 'foo';\n            });\n        });\n\n        $this->router->version('v2', ['prefix' => 'foo/bar'], function () {\n            $this->router->get('foo', function () {\n                return 'bar';\n            });\n        });\n\n        $request = $this->createRequest('/foo/bar/foo', 'GET', ['accept' => 'application/vnd.api.v2+json']);\n        $this->assertSame('bar', $this->router->dispatch($request)->getContent(), 'Router could not dispatch prefixed routes.');\n    }\n\n    public function testRoutesWithDomains()\n    {\n        $this->router->version('v1', ['domain' => 'foo.bar'], function () {\n            $this->router->get('foo', function () {\n                return 'foo';\n            });\n        });\n\n        $this->router->version('v2', ['domain' => 'foo.bar'], function () {\n            $this->router->get('foo', function () {\n                return 'bar';\n            });\n        });\n\n        $request = $this->createRequest('http://foo.bar/foo', 'GET', ['accept' => 'application/vnd.api.v2+json']);\n        $this->assertSame('bar', $this->router->dispatch($request)->getContent(), 'Router could not dispatch domain routes.');\n    }\n\n    public function testPointReleaseVersions()\n    {\n        $this->router->version('v1.1', function () {\n            $this->router->get('foo', function () {\n                return 'foo';\n            });\n        });\n\n        $this->router->version('v2.0.1', function () {\n            $this->router->get('bar', function () {\n                return 'bar';\n            });\n        });\n\n        $request = $this->createRequest('/foo', 'GET', ['accept' => 'application/vnd.api.v1.1+json']);\n        $this->assertSame('foo', $this->router->dispatch($request)->getContent(), 'Router does not support point release versions.');\n\n        $request = $this->createRequest('/bar', 'GET', ['accept' => 'application/vnd.api.v2.0.1+json']);\n        $this->assertSame('bar', $this->router->dispatch($request)->getContent(), 'Router does not support point release versions.');\n    }\n\n    public function testRoutingResources()\n    {\n        $this->router->version('v1', ['namespace' => '\\Dingo\\Api\\Tests\\Stubs'], function () {\n            $this->router->resources([\n                'bar' => ['RoutingControllerStub', ['only' => ['index']]],\n            ]);\n        });\n\n        $request = $this->createRequest('/bar', 'GET', ['accept' => 'application/vnd.api.v1+json']);\n\n        $this->assertSame('foo', $this->router->dispatch($request)->getContent(), 'Router did not register controller correctly.');\n    }\n\n    public function testIterableRoutes()\n    {\n        $this->router->version('v1', ['namespace' => '\\Dingo\\Api\\Tests\\Stubs'], function () {\n            $this->router->post('/', ['uses' => 'RoutingControllerStub@index']);\n            $this->router->post('/find', ['uses' => 'RoutingControllerOtherStub@show']);\n        });\n\n        $routes = $this->adapter->getIterableRoutes();\n        $this->assertTrue(array_key_exists('v1', (array) $routes));\n        $this->assertSame(2, count($routes['v1']));\n    }\n}\n"
  },
  {
    "path": "tests/Routing/Adapter/LaravelTest.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Tests\\Routing\\Adapter;\n\nuse Dingo\\Api\\Routing\\Adapter\\Laravel;\nuse Illuminate\\Container\\Container;\nuse Illuminate\\Events\\Dispatcher;\nuse Illuminate\\Routing\\Router;\n\nclass LaravelTest extends BaseAdapterTest\n{\n    public function getAdapterInstance()\n    {\n        return new Laravel(new Router(new Dispatcher, $this->container));\n    }\n\n    public function getContainerInstance()\n    {\n        return new Container;\n    }\n}\n"
  },
  {
    "path": "tests/Routing/Adapter/LumenTest.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Tests\\Routing\\Adapter;\n\nuse Dingo\\Api\\Routing\\Adapter\\Lumen;\nuse FastRoute\\DataGenerator\\GroupCountBased as GcbDataGenerator;\nuse FastRoute\\Dispatcher\\GroupCountBased as GcbDispatcher;\nuse FastRoute\\RouteParser\\Std as StdRouteParser;\nuse Illuminate\\Http\\Request;\nuse Laravel\\Lumen\\Application;\n\nclass LumenTest extends BaseAdapterTest\n{\n    public function getAdapterInstance()\n    {\n        $this->container->routeMiddleware([\n            'api.auth' => get_class($this->container['api.auth']),\n            'api.limiting' => get_class($this->container['api.limiting']),\n        ]);\n\n        // When we rebind the \"request\" instance during testing we'll pull the route resolver\n        // from the Lumen request instance and set it on our request so we can fetch\n        // the route properly.\n        $this->container->rebinding('request', function ($app, $request) {\n            $request->setRouteResolver($app[Request::class]->getRouteResolver());\n        });\n\n        return new Lumen($this->container, new StdRouteParser, new GcbDataGenerator, function ($routes) {\n            return new GcbDispatcher($routes->getData());\n        });\n    }\n\n    public function getContainerInstance()\n    {\n        return new Application;\n    }\n\n    public function testRoutesWithDomains()\n    {\n        $this->markTestSkipped('Lumen does not support sub-domain routing.');\n    }\n}\n"
  },
  {
    "path": "tests/Routing/RouteTest.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Tests\\Routing;\n\nuse Dingo\\Api\\Http\\Request;\nuse Dingo\\Api\\Routing\\Route;\nuse Dingo\\Api\\Tests\\BaseTestCase;\nuse Dingo\\Api\\Tests\\Stubs\\BasicThrottleStub;\nuse Dingo\\Api\\Tests\\Stubs\\RoutingAdapterStub;\nuse Dingo\\Api\\Tests\\Stubs\\RoutingControllerStub;\nuse Dingo\\Api\\Tests\\Stubs\\ThrottleStub;\nuse Illuminate\\Container\\Container;\nuse Illuminate\\Routing\\Route as IlluminateRoute;\n\nclass RouteTest extends BaseTestCase\n{\n    /**\n     * @var RoutingAdapterStub\n     */\n    protected $adapter;\n    /**\n     * @var Container\n     */\n    protected $container;\n\n    public function setUp(): void\n    {\n        $this->adapter = new RoutingAdapterStub;\n        $this->container = new Container;\n    }\n\n    public function testCreatingNewRoute()\n    {\n        $request = Request::create('foo', 'GET');\n\n        $route = new Route($this->adapter, $this->container, $request, new IlluminateRoute(['GET', 'HEAD'], 'foo', [\n            'scopes' => ['foo', 'bar'],\n            'providers' => ['foo'],\n            'limit' => 5,\n            'expires' => 10,\n            'throttle' => BasicThrottleStub::class,\n            'version' => ['v1'],\n            'conditionalRequest' => false,\n            'middleware' => 'foo.bar',\n        ]));\n\n        $this->assertSame(['foo', 'bar'], $route->scopes(), 'Route did not setup scopes correctly.');\n        $this->assertSame(['foo'], $route->getAuthenticationProviders(), 'Route did not setup authentication providers correctly.');\n        $this->assertSame(5, $route->getRateLimit(), 'Route did not setup rate limit correctly.');\n        $this->assertSame(10, $route->getRateLimitExpiration(), 'Route did not setup rate limit expiration correctly.');\n        $this->assertTrue($route->hasThrottle(), 'Route did not setup throttle correctly.');\n        $this->assertInstanceOf(BasicThrottleStub::class, $route->getThrottle(), 'Route did not setup throttle correctly.');\n        $this->assertFalse($route->requestIsConditional(), 'Route did not setup conditional request correctly.');\n    }\n\n    public function testControllerOptionsMergeAndOverrideRouteOptions()\n    {\n        $request = Request::create('foo', 'GET');\n\n        $route = new Route($this->adapter, $this->container, $request, new IlluminateRoute(['GET', 'HEAD'], 'foo', [\n            'scopes' => ['foo', 'bar'],\n            'providers' => ['foo'],\n            'limit' => 5,\n            'expires' => 10,\n            'throttle' => ThrottleStub::class,\n            'version' => ['v1'],\n            'conditionalRequest' => false,\n            'uses' => RoutingControllerStub::class.'@index',\n            'middleware' => 'foo.bar',\n        ]));\n\n        $this->assertSame(['foo', 'bar', 'baz', 'bing'], $route->scopes(), 'Route did not setup scopes correctly.');\n        $this->assertSame(['foo', 'red', 'black'], $route->getAuthenticationProviders(), 'Route did not setup authentication providers correctly.');\n        $this->assertSame(10, $route->getRateLimit(), 'Route did not setup rate limit correctly.');\n        $this->assertSame(20, $route->getRateLimitExpiration(), 'Route did not setup rate limit expiration correctly.');\n        $this->assertTrue($route->hasThrottle(), 'Route did not setup throttle correctly.');\n        $this->assertInstanceOf(BasicThrottleStub::class, $route->getThrottle(), 'Route did not setup throttle correctly.');\n\n        $route = new Route($this->adapter, $this->container, $request, new IlluminateRoute(['GET', 'HEAD'], 'foo/bar', [\n            'scopes' => ['foo', 'bar'],\n            'providers' => ['foo'],\n            'limit' => 5,\n            'expires' => 10,\n            'throttle' => ThrottleStub::class,\n            'version' => ['v1'],\n            'conditionalRequest' => false,\n            'uses' => RoutingControllerStub::class.'@show',\n        ]));\n\n        $this->assertSame(['foo', 'bar', 'baz', 'bing', 'bob'], $route->scopes(), 'Route did not setup scopes correctly.');\n        $this->assertSame(['foo'], $route->getAuthenticationProviders(), 'Route did not setup authentication providers correctly.');\n        $this->assertSame(10, $route->getRateLimit(), 'Route did not setup rate limit correctly.');\n        $this->assertSame(20, $route->getRateLimitExpiration(), 'Route did not setup rate limit expiration correctly.');\n        $this->assertTrue($route->hasThrottle(), 'Route did not setup throttle correctly.');\n        $this->assertInstanceOf(BasicThrottleStub::class, $route->getThrottle(), 'Route did not setup throttle correctly.');\n    }\n}\n"
  },
  {
    "path": "tests/Routing/RouterTest.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Tests\\Routing;\n\nuse Dingo\\Api\\Http;\nuse Dingo\\Api\\Routing\\Route;\nuse Dingo\\Api\\Routing\\Router;\nuse Dingo\\Api\\Tests\\Stubs\\BasicThrottleStub;\nuse Dingo\\Api\\Tests\\Stubs\\RoutingAdapterStub;\nuse Dingo\\Api\\Tests\\Stubs\\RoutingControllerStub;\nuse Dingo\\Api\\Tests\\Stubs\\ThrottleStub;\nuse Illuminate\\Container\\Container;\nuse Mockery as m;\nuse Symfony\\Component\\HttpKernel\\Exception\\HttpException;\n\nclass RouterTest extends Adapter\\BaseAdapterTest\n{\n    public function getAdapterInstance()\n    {\n        return $this->container->make(RoutingAdapterStub::class);\n    }\n\n    public function getContainerInstance()\n    {\n        return new Container;\n    }\n\n    public function testRouteOptionsMergeCorrectly()\n    {\n        $this->router->version('v1', ['scopes' => 'foo|bar'], function () {\n            $this->router->get('foo', ['scopes' => ['baz'], function () {\n                $this->assertSame(\n                    ['foo', 'bar', 'baz'],\n                    $this->router->getCurrentRoute()->getScopes(),\n                    'Router did not merge string based group scopes with route based array scopes.'\n                );\n            }]);\n\n            $this->router->get('baz', function () {\n                $this->assertSame(\n                    ['foo', 'bar'],\n                    $this->router->getCurrentRoute()->getScopes(),\n                    'Router did not merge string based group scopes with route.'\n                );\n            });\n        });\n\n        $request = $this->createRequest('foo', 'GET', ['accept' => 'application/vnd.api.v1+json']);\n        $this->router->dispatch($request);\n\n        $request = $this->createRequest('baz', 'GET', ['accept' => 'application/vnd.api.v1+json']);\n        $this->router->dispatch($request);\n\n        $this->router->version('v2', ['providers' => 'foo', 'throttle' => new ThrottleStub(['limit' => 10, 'expires' => 15]), 'namespace' => '\\Dingo\\Api\\Tests'], function () {\n            $this->router->get('foo', 'Stubs\\RoutingControllerStub@index');\n        });\n\n        $request = $this->createRequest('foo', 'GET', ['accept' => 'application/vnd.api.v2+json']);\n        $this->router->dispatch($request);\n\n        $route = $this->router->getCurrentRoute();\n\n        $this->assertSame(['baz', 'bing'], $route->scopes());\n        $this->assertSame(['foo', 'red', 'black'], $route->getAuthenticationProviders());\n        $this->assertSame(10, $route->getRateLimit());\n        $this->assertSame(20, $route->getRateLimitExpiration());\n        $this->assertInstanceOf(BasicThrottleStub::class, $route->getThrottle());\n    }\n\n    public function testGroupAsPrefixesRouteAs()\n    {\n        $this->router->version('v1', ['as' => 'api'], function ($api) {\n            $api->get('users', ['as' => 'users', function () {\n                return 'foo';\n            }]);\n        });\n\n        $routes = $this->router->getRoutes('v1');\n\n        $this->assertInstanceOf(Route::class, $routes->getByName('api.users'));\n    }\n\n    public function testNoGroupVersionThrowsException()\n    {\n        $this->expectException(\\RuntimeException::class);\n        $this->expectExceptionMessage('A version is required for an API group definition.');\n\n        $this->router->group([], function () {\n            //\n        });\n    }\n\n    public function testMatchRoutes()\n    {\n        $this->router->version('v1', function ($api) {\n            $api->match(['get', 'post'], 'foo', function () {\n                return 'bar';\n            });\n        });\n\n        $this->router->setConditionalRequest(false);\n\n        $response = $this->router->dispatch(\n            $request = $this->createRequest('foo', 'GET', ['accept' => 'application/vnd.api.v1+json'])\n        );\n\n        $this->assertSame(200, $response->getStatusCode());\n        $this->assertSame('bar', $response->getContent());\n\n        $response = $this->router->dispatch(\n            $request = $this->createRequest('foo', 'POST', ['accept' => 'application/vnd.api.v1+json'])\n        );\n\n        $this->assertSame(200, $response->getStatusCode());\n        $this->assertSame('bar', $response->getContent());\n    }\n\n    public function testAnyRoutes()\n    {\n        $this->router->version('v1', function ($api) {\n            $api->any('foo', function () {\n                return 'bar';\n            });\n        });\n\n        $this->router->setConditionalRequest(false);\n\n        $response = $this->router->dispatch(\n            $request = $this->createRequest('foo', 'GET', ['accept' => 'application/vnd.api.v1+json'])\n        );\n\n        $this->assertSame(200, $response->getStatusCode());\n        $this->assertSame('bar', $response->getContent());\n\n        $response = $this->router->dispatch(\n            $request = $this->createRequest('foo', 'POST', ['accept' => 'application/vnd.api.v1+json'])\n        );\n\n        $this->assertSame(200, $response->getStatusCode());\n        $this->assertSame('bar', $response->getContent());\n\n        $response = $this->router->dispatch(\n            $request = $this->createRequest('foo', 'PATCH', ['accept' => 'application/vnd.api.v1+json'])\n        );\n\n        $this->assertSame(200, $response->getStatusCode());\n        $this->assertSame('bar', $response->getContent());\n\n        $response = $this->router->dispatch(\n            $request = $this->createRequest('foo', 'DELETE', ['accept' => 'application/vnd.api.v1+json'])\n        );\n\n        $this->assertSame(200, $response->getStatusCode());\n        $this->assertSame('bar', $response->getContent());\n    }\n\n    public function testRouterPreparesNotModifiedResponse()\n    {\n        $this->router->version('v1', function () {\n            $this->router->get('foo', function () {\n                return 'bar';\n            });\n        });\n\n        $this->router->setConditionalRequest(false);\n\n        $response = $this->router->dispatch(\n            $request = $this->createRequest('foo', 'GET', ['accept' => 'application/vnd.api.v1+json'])\n        );\n\n        $this->assertSame(200, $response->getStatusCode());\n        $this->assertSame('bar', $response->getContent());\n\n        $this->router->setConditionalRequest(true);\n\n        $response = $this->router->dispatch($request);\n\n        $this->assertSame(200, $response->getStatusCode());\n        $this->assertSame('\"'.sha1('bar').'\"', $response->getETag());\n        $this->assertSame('bar', $response->getContent());\n\n        $request = $this->createRequest('foo', 'GET', [\n            'if-none-match' => '\"'.sha1('bar').'\"',\n            'accept' => 'application/vnd.api.v1+json',\n        ]);\n\n        $response = $this->router->dispatch($request);\n\n        $this->assertSame(304, $response->getStatusCode());\n        $this->assertSame('\"'.sha1('bar').'\"', $response->getETag());\n        $this->assertEmpty($response->getContent());\n\n        $request = $this->createRequest('foo', 'GET', [\n            'if-none-match' => '123456789',\n            'accept' => 'application/vnd.api.v1+json',\n        ]);\n\n        $response = $this->router->dispatch($request);\n\n        $this->assertSame(200, $response->getStatusCode());\n        $this->assertSame('\"'.sha1('bar').'\"', $response->getETag());\n        $this->assertSame('bar', $response->getContent());\n    }\n\n    public function testRouterHandlesExistingEtag()\n    {\n        $this->router->version('v1', ['conditional_request' => true], function () {\n            $this->router->get('foo', function () {\n                $response = new Http\\Response('bar');\n                $response->setEtag('custom-etag');\n\n                return $response;\n            });\n        });\n\n        $response = $this->router->dispatch(\n            $this->createRequest('foo', 'GET', ['accept' => 'application/vnd.api.v1+json'])\n        );\n\n        $this->assertSame(200, $response->getStatusCode());\n        $this->assertSame('\"custom-etag\"', $response->getETag());\n        $this->assertSame('bar', $response->getContent());\n    }\n\n    public function testRouterHandlesCustomEtag()\n    {\n        $this->router->version('v1', ['conditional_request' => true], function () {\n            $this->router->get('foo', function () {\n                $response = new Http\\Response('bar');\n                $response->setEtag('custom-etag');\n\n                return $response;\n            });\n        });\n\n        $response = $this->router->dispatch(\n            $this->createRequest('foo', 'GET', [\n                'if-none-match' => '\"custom-etag\"',\n                'accept' => 'application/vnd.api.v1+json',\n            ])\n        );\n\n        $this->assertSame(304, $response->getStatusCode());\n        $this->assertSame('\"custom-etag\"', $response->getETag());\n        $this->assertEmpty($response->getContent());\n    }\n\n    public function testExceptionsAreHandledByExceptionHandler()\n    {\n        $exception = new HttpException(400);\n\n        $this->router->version('v1', function () use ($exception) {\n            $this->router->get('foo', function () use ($exception) {\n                throw $exception;\n            });\n        });\n\n        $this->exception->shouldReceive('report')->once()->with($exception);\n        $this->exception->shouldReceive('handle')->once()->with($exception)->andReturn(new Http\\Response('exception'));\n\n        $request = $this->createRequest('foo', 'GET', ['accept' => 'application/vnd.api.v1+json']);\n\n        $this->assertSame('exception', $this->router->dispatch($request)->getContent(), 'Router did not delegate exception handling.');\n    }\n\n    public function testNoAcceptHeaderUsesDefaultVersion()\n    {\n        $this->router->version('v1', function () {\n            $this->router->get('foo', function () {\n                return 'foo';\n            });\n        });\n\n        $this->assertSame('foo', $this->router->dispatch($this->createRequest('foo', 'GET'))->getContent(), 'Router does not default to default version.');\n    }\n\n    public function testRoutesAddedToCorrectVersions()\n    {\n        $this->router->version('v1', ['domain' => 'foo.bar'], function () {\n            $this->router->get('foo', function () {\n                return 'bar';\n            });\n        });\n\n        $this->router->version('v2', ['domain' => 'foo.bar'], function () {\n            $this->router->get('bar', function () {\n                return 'baz';\n            });\n        });\n\n        $this->createRequest('/', 'GET');\n\n        $this->assertCount(1, $this->router->getRoutes()['v1'], 'Routes were not added to the correct versions.');\n    }\n\n    public function testUnsuccessfulResponseThrowsHttpException()\n    {\n        $this->router->version('v1', function () {\n            $this->router->get('foo', function () {\n                return new Http\\Response('Failed!', 400);\n            });\n        });\n\n        $request = $this->createRequest('foo', 'GET');\n\n        $this->exception->shouldReceive('handle')->with(m::type(HttpException::class))->andReturn(new Http\\Response('Failed!'));\n\n        $this->assertSame('Failed!', $this->router->dispatch($request)->getContent(), 'Router did not throw and handle a HttpException.');\n    }\n\n    public function testGroupNamespacesAreConcatenated()\n    {\n        $this->router->version('v1', ['namespace' => '\\Dingo\\Api'], function () {\n            $this->router->group(['namespace' => 'Tests\\Stubs'], function () {\n                $this->router->get('foo', 'RoutingControllerStub@getIndex');\n            });\n        });\n\n        $request = $this->createRequest('foo', 'GET');\n\n        $this->assertSame('foo', $this->router->dispatch($request)->getContent(), 'Router did not concatenate controller namespace correctly.');\n    }\n\n    public function testCurrentRouteName()\n    {\n        $this->router->version('v1', function () {\n            $this->router->get('foo', ['as' => 'foo', function () {\n                return 'foo';\n            }]);\n        });\n\n        $request = $this->createRequest('foo', 'GET');\n\n        $this->router->dispatch($request);\n\n        $this->assertFalse($this->router->currentRouteNamed('bar'));\n        $this->assertTrue($this->router->currentRouteNamed('foo'));\n        $this->assertTrue($this->router->is('*'));\n        $this->assertFalse($this->router->is('b*'));\n        $this->assertTrue($this->router->is('b*', 'f*'));\n    }\n\n    public function testCurrentRouteAction()\n    {\n        $this->router->version('v1', ['namespace' => '\\Dingo\\Api\\Tests\\Stubs'], function () {\n            $this->router->get('foo', 'RoutingControllerStub@getIndex');\n        });\n\n        $request = $this->createRequest('foo', 'GET');\n\n        $this->router->dispatch($request);\n\n        $this->assertFalse($this->router->currentRouteUses('foo'));\n        $this->assertTrue($this->router->currentRouteUses(RoutingControllerStub::class.'@getIndex'));\n        $this->assertFalse($this->router->uses('foo*'));\n        $this->assertTrue($this->router->uses('*'));\n        $this->assertTrue($this->router->uses(RoutingControllerStub::class.'@*'));\n    }\n\n    public function testRoutePatternsAreAppliedCorrectly()\n    {\n        $adapter = $this->adapter;\n        $adapter->pattern('bar', '[0-9]+');\n\n        $this->router = new Router($adapter, $this->exception, $this->container, null, null);\n        $this->router->version('v1', function ($api) {\n            $api->any('foo/{bar}', function () {\n                return 'bar';\n            });\n        });\n\n        $this->router->setConditionalRequest(false);\n\n        $this->exception->shouldReceive('report')->once()->with(HttpException::class);\n        $this->exception->shouldReceive('handle')->with(m::type(HttpException::class))->andReturn(new Http\\Response('Not Found!', 404));\n\n        $response = $this->router->dispatch(\n            $request = $this->createRequest('foo/abc', 'GET', ['accept' => 'application/vnd.api.v1+json'])\n        );\n\n        $this->assertSame(404, $response->getStatusCode());\n        $this->assertSame('Not Found!', $response->getContent());\n    }\n}\n"
  },
  {
    "path": "tests/Stubs/Application58Stub.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Tests\\Stubs;\n\nuse Closure;\nuse Illuminate\\Container\\Container;\nuse Illuminate\\Contracts\\Foundation\\Application;\n\nclass Application58Stub extends Container implements Application\n{\n    public function version()\n    {\n        return 'v1';\n    }\n\n    public function basePath()\n    {\n        //\n    }\n\n    public function bootstrapPath($path = '')\n    {\n        //\n    }\n\n    public function configPath($path = '')\n    {\n        //\n    }\n\n    public function databasePath($path = '')\n    {\n        //\n    }\n\n    public function environmentPath()\n    {\n        //\n    }\n\n    public function resourcePath($path = '')\n    {\n        //\n    }\n\n    public function storagePath()\n    {\n        //\n    }\n\n    public function environment(...$environments)\n    {\n        return 'testing';\n    }\n\n    public function runningInConsole()\n    {\n        //\n    }\n\n    public function runningUnitTests()\n    {\n        // TODO: Implement runningUnitTests() method.\n    }\n\n    public function isDownForMaintenance()\n    {\n        return false;\n    }\n\n    public function registerConfiguredProviders()\n    {\n        //\n    }\n\n    public function register($provider, $options = [], $force = false)\n    {\n        //\n    }\n\n    public function registerDeferredProvider($provider, $service = null)\n    {\n        //\n    }\n\n    public function resolveProvider($provider)\n    {\n        //\n    }\n\n    public function boot()\n    {\n        //\n    }\n\n    public function booting($callback)\n    {\n        //\n    }\n\n    public function booted($callback)\n    {\n        //\n    }\n\n    public function bootstrapWith(array $bootstrappers)\n    {\n        //\n    }\n\n    public function configurationIsCached()\n    {\n        //\n    }\n\n    public function detectEnvironment(Closure $callback)\n    {\n        //\n    }\n\n    public function environmentFile()\n    {\n        //\n    }\n\n    public function environmentFilePath()\n    {\n        //\n    }\n\n    public function getCachedConfigPath()\n    {\n        //\n    }\n\n    public function getCachedServicesPath()\n    {\n        //\n    }\n\n    public function getCachedPackagesPath()\n    {\n        //\n    }\n\n    public function getCachedRoutesPath()\n    {\n        //\n    }\n\n    public function getLocale()\n    {\n        //\n    }\n\n    public function getNamespace()\n    {\n        //\n    }\n\n    public function getProviders($provider)\n    {\n        //\n    }\n\n    public function hasBeenBootstrapped()\n    {\n        //\n    }\n\n    public function loadDeferredProviders()\n    {\n        //\n    }\n\n    public function loadEnvironmentFrom($file)\n    {\n        //\n    }\n\n    public function routesAreCached()\n    {\n        //\n    }\n\n    public function setLocale($locale)\n    {\n        //\n    }\n\n    public function shouldSkipMiddleware()\n    {\n        //\n    }\n\n    public function terminate()\n    {\n        //\n    }\n}\n"
  },
  {
    "path": "tests/Stubs/Application6Stub.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Tests\\Stubs;\n\nuse Closure;\nuse Illuminate\\Container\\Container;\nuse Illuminate\\Contracts\\Foundation\\Application;\n\nclass Application6Stub extends Container implements Application\n{\n    public function version()\n    {\n        return 'v1';\n    }\n\n    public function basePath($path = '')\n    {\n        //\n    }\n\n    public function bootstrapPath($path = '')\n    {\n        //\n    }\n\n    public function configPath($path = '')\n    {\n        //\n    }\n\n    public function databasePath($path = '')\n    {\n        //\n    }\n\n    public function environmentPath()\n    {\n        //\n    }\n\n    public function resourcePath($path = '')\n    {\n        //\n    }\n\n    public function storagePath()\n    {\n        //\n    }\n\n    public function environment(...$environments)\n    {\n        return 'testing';\n    }\n\n    public function runningInConsole()\n    {\n        //\n    }\n\n    public function runningUnitTests()\n    {\n        // TODO: Implement runningUnitTests() method.\n    }\n\n    public function isDownForMaintenance()\n    {\n        return false;\n    }\n\n    public function registerConfiguredProviders()\n    {\n        //\n    }\n\n    public function register($provider, $options = [], $force = false)\n    {\n        //\n    }\n\n    public function registerDeferredProvider($provider, $service = null)\n    {\n        //\n    }\n\n    public function resolveProvider($provider)\n    {\n        //\n    }\n\n    public function boot()\n    {\n        //\n    }\n\n    public function booting($callback)\n    {\n        //\n    }\n\n    public function booted($callback)\n    {\n        //\n    }\n\n    public function bootstrapWith(array $bootstrappers)\n    {\n        //\n    }\n\n    public function configurationIsCached()\n    {\n        //\n    }\n\n    public function detectEnvironment(Closure $callback)\n    {\n        //\n    }\n\n    public function environmentFile()\n    {\n        //\n    }\n\n    public function environmentFilePath()\n    {\n        //\n    }\n\n    public function getCachedConfigPath()\n    {\n        //\n    }\n\n    public function getCachedServicesPath()\n    {\n        //\n    }\n\n    public function getCachedPackagesPath()\n    {\n        //\n    }\n\n    public function getCachedRoutesPath()\n    {\n        //\n    }\n\n    public function getLocale()\n    {\n        //\n    }\n\n    public function getNamespace()\n    {\n        //\n    }\n\n    public function getProviders($provider)\n    {\n        //\n    }\n\n    public function hasBeenBootstrapped()\n    {\n        //\n    }\n\n    public function loadDeferredProviders()\n    {\n        //\n    }\n\n    public function loadEnvironmentFrom($file)\n    {\n        //\n    }\n\n    public function routesAreCached()\n    {\n        //\n    }\n\n    public function setLocale($locale)\n    {\n        //\n    }\n\n    public function shouldSkipMiddleware()\n    {\n        //\n    }\n\n    public function terminate()\n    {\n        //\n    }\n}\n"
  },
  {
    "path": "tests/Stubs/Application7Stub.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Tests\\Stubs;\n\nuse Illuminate\\Container\\Container;\nuse Illuminate\\Contracts\\Foundation\\Application;\n\nclass Application7Stub extends Container implements Application\n{\n    public function version()\n    {\n        return 'v1';\n    }\n\n    public function basePath($path = '')\n    {\n        //\n    }\n\n    public function bootstrapPath($path = '')\n    {\n        //\n    }\n\n    public function configPath($path = '')\n    {\n        //\n    }\n\n    public function databasePath($path = '')\n    {\n        //\n    }\n\n    public function environmentPath()\n    {\n        //\n    }\n\n    public function resourcePath($path = '')\n    {\n        //\n    }\n\n    public function storagePath()\n    {\n        //\n    }\n\n    public function environment(...$environments)\n    {\n        return 'testing';\n    }\n\n    public function runningInConsole()\n    {\n        //\n    }\n\n    public function runningUnitTests()\n    {\n        // TODO: Implement runningUnitTests() method.\n    }\n\n    public function isDownForMaintenance()\n    {\n        return false;\n    }\n\n    public function registerConfiguredProviders()\n    {\n        //\n    }\n\n    public function register($provider, $options = [], $force = false)\n    {\n        //\n    }\n\n    public function registerDeferredProvider($provider, $service = null)\n    {\n        //\n    }\n\n    public function resolveProvider($provider)\n    {\n        //\n    }\n\n    public function boot()\n    {\n        //\n    }\n\n    public function booting($callback)\n    {\n        //\n    }\n\n    public function booted($callback)\n    {\n        //\n    }\n\n    public function bootstrapWith(array $bootstrappers)\n    {\n        //\n    }\n\n    public function configurationIsCached()\n    {\n        //\n    }\n\n    public function detectEnvironment(\\Closure $callback)\n    {\n        //\n    }\n\n    public function environmentFile()\n    {\n        //\n    }\n\n    public function environmentFilePath()\n    {\n        //\n    }\n\n    public function getCachedConfigPath()\n    {\n        //\n    }\n\n    public function getCachedServicesPath()\n    {\n        //\n    }\n\n    public function getCachedPackagesPath()\n    {\n        //\n    }\n\n    public function getCachedRoutesPath()\n    {\n        //\n    }\n\n    public function getLocale()\n    {\n        //\n    }\n\n    public function getNamespace()\n    {\n        //\n    }\n\n    public function getProviders($provider)\n    {\n        //\n    }\n\n    public function hasBeenBootstrapped()\n    {\n        //\n    }\n\n    public function loadDeferredProviders()\n    {\n        //\n    }\n\n    public function loadEnvironmentFrom($file)\n    {\n        //\n    }\n\n    public function routesAreCached()\n    {\n        //\n    }\n\n    public function setLocale($locale)\n    {\n        //\n    }\n\n    public function shouldSkipMiddleware()\n    {\n        //\n    }\n\n    public function terminate()\n    {\n        //\n    }\n}\n"
  },
  {
    "path": "tests/Stubs/Application8Stub.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Tests\\Stubs;\n\nuse Illuminate\\Container\\Container;\nuse Illuminate\\Contracts\\Foundation\\Application;\n\nclass Application8Stub extends Container implements Application\n{\n    public function version()\n    {\n        return 'v1';\n    }\n\n    public function basePath($path = '')\n    {\n        //\n    }\n\n    public function bootstrapPath($path = '')\n    {\n        //\n    }\n\n    public function configPath($path = '')\n    {\n        //\n    }\n\n    public function databasePath($path = '')\n    {\n        //\n    }\n\n    public function environmentPath()\n    {\n        //\n    }\n\n    public function resourcePath($path = '')\n    {\n        //\n    }\n\n    public function storagePath()\n    {\n        //\n    }\n\n    public function environment(...$environments)\n    {\n        return 'testing';\n    }\n\n    public function runningInConsole()\n    {\n        //\n    }\n\n    public function runningUnitTests()\n    {\n        // TODO: Implement runningUnitTests() method.\n    }\n\n    public function isDownForMaintenance()\n    {\n        return false;\n    }\n\n    public function registerConfiguredProviders()\n    {\n        //\n    }\n\n    public function register($provider, $options = [], $force = false)\n    {\n        //\n    }\n\n    public function registerDeferredProvider($provider, $service = null)\n    {\n        //\n    }\n\n    public function resolveProvider($provider)\n    {\n        //\n    }\n\n    public function boot()\n    {\n        //\n    }\n\n    public function booting($callback)\n    {\n        //\n    }\n\n    public function booted($callback)\n    {\n        //\n    }\n\n    public function bootstrapWith(array $bootstrappers)\n    {\n        //\n    }\n\n    public function configurationIsCached()\n    {\n        //\n    }\n\n    public function detectEnvironment(\\Closure $callback)\n    {\n        //\n    }\n\n    public function environmentFile()\n    {\n        //\n    }\n\n    public function environmentFilePath()\n    {\n        //\n    }\n\n    public function getCachedConfigPath()\n    {\n        //\n    }\n\n    public function getCachedServicesPath()\n    {\n        //\n    }\n\n    public function getCachedPackagesPath()\n    {\n        //\n    }\n\n    public function getCachedRoutesPath()\n    {\n        //\n    }\n\n    public function getLocale()\n    {\n        //\n    }\n\n    public function getNamespace()\n    {\n        //\n    }\n\n    public function getProviders($provider)\n    {\n        //\n    }\n\n    public function hasBeenBootstrapped()\n    {\n        //\n    }\n\n    public function loadDeferredProviders()\n    {\n        //\n    }\n\n    public function loadEnvironmentFrom($file)\n    {\n        //\n    }\n\n    public function routesAreCached()\n    {\n        //\n    }\n\n    public function setLocale($locale)\n    {\n        //\n    }\n\n    public function shouldSkipMiddleware()\n    {\n        //\n    }\n\n    public function terminate()\n    {\n        //\n    }\n}\n"
  },
  {
    "path": "tests/Stubs/ApplicationStub.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Tests\\Stubs;\n\nuse Illuminate\\Container\\Container;\nuse Illuminate\\Contracts\\Foundation\\Application;\n\nclass ApplicationStub extends Container implements Application\n{\n    public function version()\n    {\n        return 'v1';\n    }\n\n    public function basePath()\n    {\n        //\n    }\n\n    public function environment()\n    {\n        return 'testing';\n    }\n\n    public function isDownForMaintenance()\n    {\n        return false;\n    }\n\n    public function registerConfiguredProviders()\n    {\n        //\n    }\n\n    public function register($provider, $options = [], $force = false)\n    {\n        //\n    }\n\n    public function runningUnitTests()\n    {\n        // TODO: Implement runningUnitTests() method.\n    }\n\n    public function registerDeferredProvider($provider, $service = null)\n    {\n        //\n    }\n\n    public function getCachedCompilePath()\n    {\n        //\n    }\n\n    public function getCachedServicesPath()\n    {\n        //\n    }\n\n    public function boot()\n    {\n        //\n    }\n\n    public function booting($callback)\n    {\n        //\n    }\n\n    public function booted($callback)\n    {\n        //\n    }\n\n    public function getCachedPackagesPath()\n    {\n        //\n    }\n\n    public function runningInConsole()\n    {\n        //\n    }\n}\n"
  },
  {
    "path": "tests/Stubs/AuthorizationProviderStub.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Tests\\Stubs;\n\nuse Dingo\\Api\\Auth\\Provider\\Authorization;\nuse Dingo\\Api\\Routing\\Route;\nuse Illuminate\\Http\\Request;\n\nclass AuthorizationProviderStub extends Authorization\n{\n    public function authenticate(Request $request, Route $route)\n    {\n        $this->validateAuthorizationHeader($request);\n    }\n\n    public function getAuthorizationMethod()\n    {\n        return 'foo';\n    }\n}\n"
  },
  {
    "path": "tests/Stubs/BasicThrottleStub.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Tests\\Stubs;\n\nuse Dingo\\Api\\Contract\\Http\\RateLimit\\Throttle;\nuse Illuminate\\Container\\Container;\n\nclass BasicThrottleStub implements Throttle\n{\n    public function match(Container $app)\n    {\n        return true;\n    }\n\n    public function getLimit()\n    {\n        return 15;\n    }\n\n    public function getExpires()\n    {\n        return 10;\n    }\n}\n"
  },
  {
    "path": "tests/Stubs/EloquentModelStub.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Tests\\Stubs;\n\nuse Illuminate\\Database\\Eloquent\\Model;\n\nclass EloquentModelStub extends Model\n{\n    protected $table = 'foo_bar';\n\n    public function toArray()\n    {\n        return ['foo' => 'bar'];\n    }\n}\n"
  },
  {
    "path": "tests/Stubs/HttpValidatorStub.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Tests\\Stubs;\n\nuse Dingo\\Api\\Contract\\Http\\Validator;\nuse Illuminate\\Http\\Request;\n\nclass HttpValidatorStub implements Validator\n{\n    public function validate(Request $request)\n    {\n        return $request->getMethod() === 'POST';\n    }\n}\n"
  },
  {
    "path": "tests/Stubs/MiddlewareStub.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Tests\\Stubs;\n\nuse Closure;\n\nclass MiddlewareStub\n{\n    public function handle($request, Closure $next)\n    {\n        return $next($request);\n    }\n}\n"
  },
  {
    "path": "tests/Stubs/RoutingAdapterStub.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Tests\\Stubs;\n\nuse Closure;\nuse Dingo\\Api\\Contract\\Routing\\Adapter;\nuse Dingo\\Api\\Http\\Response;\nuse Illuminate\\Container\\Container;\nuse Illuminate\\Http\\JsonResponse;\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Http\\Response as IlluminateResponse;\nuse Illuminate\\Pipeline\\Pipeline;\nuse Illuminate\\Routing\\Route as IlluminateRoute;\nuse Illuminate\\Routing\\RouteCollection;\n\nclass RoutingAdapterStub implements Adapter\n{\n    protected $routes = [];\n\n    protected $patterns = [];\n\n    public function dispatch(Request $request, $version)\n    {\n        $routes = $this->routes[$version];\n\n        $route = $this->findRoute($request, $routes);\n\n        $request->setRouteResolver(function () use ($route) {\n            return $route;\n        });\n\n        return (new Pipeline(new Container))\n            ->send($request)\n            ->through([])\n            ->then(function ($request) use ($route) {\n                return $this->prepareResponse($request, $route->run($request));\n            });\n    }\n\n    protected function findRouteClosure(array $action)\n    {\n        foreach ($action as $value) {\n            if ($value instanceof Closure) {\n                return $value;\n            }\n        }\n    }\n\n    protected function prepareResponse($request, $response)\n    {\n        if ($response instanceof IlluminateResponse) {\n            $response = Response::makeFromExisting($response);\n        } elseif ($response instanceof JsonResponse) {\n            $response = Response::makeFromJson($response);\n        } else {\n            $response = new Response($response);\n        }\n\n        return $response->prepare($request);\n    }\n\n    protected function findRoute(Request $request, $routeCollection)\n    {\n        return $routeCollection->match($request);\n    }\n\n    public function getRouteProperties($route, Request $request)\n    {\n        return [$route->uri(), (array) $request->getMethod(), $route->getAction()];\n    }\n\n    public function addRoute(array $methods, array $versions, $uri, $action)\n    {\n        $this->createRouteCollections($versions);\n\n        $route = new IlluminateRoute($methods, $uri, $action);\n        $this->addWhereClausesToRoute($route);\n\n        foreach ($versions as $version) {\n            $this->routes[$version]->add($route);\n        }\n\n        return $route;\n    }\n\n    public function getRoutes($version = null)\n    {\n        if (! is_null($version)) {\n            return $this->routes[$version];\n        }\n\n        return $this->routes;\n    }\n\n    public function getIterableRoutes($version = null)\n    {\n        return $this->getRoutes($version);\n    }\n\n    public function setRoutes(array $routes)\n    {\n        //\n    }\n\n    public function prepareRouteForSerialization($route)\n    {\n        //\n    }\n\n    public function pattern($key, $pattern)\n    {\n        $this->patterns[$key] = $pattern;\n    }\n\n    public function getPatterns()\n    {\n        return $this->patterns;\n    }\n\n    protected function createRouteCollections(array $versions)\n    {\n        foreach ($versions as $version) {\n            if (! isset($this->routes[$version])) {\n                $this->routes[$version] = new RouteCollection;\n            }\n        }\n    }\n\n    protected function addWhereClausesToRoute($route)\n    {\n        $where = isset($route->getAction()['where']) ? $route->getAction()['where'] : [];\n\n        $route->where(array_merge($this->patterns, $where));\n\n        return $route;\n    }\n}\n"
  },
  {
    "path": "tests/Stubs/RoutingControllerOtherStub.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Tests\\Stubs;\n\nuse Illuminate\\Routing\\Controller;\n\nclass RoutingControllerOtherStub extends Controller\n{\n    public function find()\n    {\n        return 'baz';\n    }\n}\n"
  },
  {
    "path": "tests/Stubs/RoutingControllerStub.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Tests\\Stubs;\n\nuse Dingo\\Api\\Routing\\Helpers;\nuse Illuminate\\Routing\\Controller;\n\nclass RoutingControllerStub extends Controller\n{\n    use Helpers;\n\n    public function __construct()\n    {\n        $this->scopes('baz|bing');\n        $this->scopes('bob', ['except' => ['index']]);\n\n        $this->authenticateWith('red|black', ['only' => 'index']);\n\n        $this->rateLimit(10, 20);\n\n        $this->throttle(BasicThrottleStub::class);\n    }\n\n    public function index()\n    {\n        return 'foo';\n    }\n\n    public function show()\n    {\n        return 'bar';\n    }\n\n    public function getIndex()\n    {\n        return 'foo';\n    }\n}\n"
  },
  {
    "path": "tests/Stubs/ThrottleStub.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Tests\\Stubs;\n\nuse Dingo\\Api\\Http\\RateLimit\\Throttle\\Throttle;\nuse Illuminate\\Container\\Container;\n\nclass ThrottleStub extends Throttle\n{\n    protected $enabled;\n\n    public function __construct(array $options = ['limit' => 60, 'expires' => 60], $enabled = true)\n    {\n        $this->enabled = $enabled;\n\n        parent::__construct($options);\n    }\n\n    public function match(Container $app)\n    {\n        return $this->enabled;\n    }\n}\n"
  },
  {
    "path": "tests/Stubs/TransformerStub.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Tests\\Stubs;\n\nuse Dingo\\Api\\Contract\\Transformer\\Adapter;\nuse Dingo\\Api\\Http\\Request;\nuse Dingo\\Api\\Transformer\\Binding;\nuse Illuminate\\Support\\Collection;\n\nclass TransformerStub implements Adapter\n{\n    public function transform($response, $transformer, Binding $binding, Request $request)\n    {\n        if ($response instanceof Collection) {\n            return $response->transform(function ($response) use ($transformer) {\n                return $transformer->transform($response);\n            })->toArray();\n        }\n\n        return $transformer->transform($response);\n    }\n}\n"
  },
  {
    "path": "tests/Stubs/UserStub.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Tests\\Stubs;\n\nclass UserStub\n{\n    public $name;\n\n    public function __construct($name)\n    {\n        $this->name = $name;\n    }\n}\n"
  },
  {
    "path": "tests/Stubs/UserTransformerStub.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Tests\\Stubs;\n\nclass UserTransformerStub\n{\n    public function transform(UserStub $user)\n    {\n        return [\n            'name' => $user->name,\n        ];\n    }\n}\n"
  },
  {
    "path": "tests/Transformer/Adapter/FractalTest.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Tests\\Transformer\\Adapter;\n\nuse Dingo\\Api\\Http\\Request;\nuse Dingo\\Api\\Tests\\BaseTestCase;\nuse Dingo\\Api\\Transformer\\Adapter\\Fractal;\nuse League\\Fractal\\Manager as FractalManager;\n\nclass FractalTest extends BaseTestCase\n{\n    protected $fractal;\n\n    public function setUp(): void\n    {\n        $this->fractal = new Fractal(new FractalManager());\n    }\n\n    public function testParseFractalIncludes()\n    {\n        $request = Request::create('/?include=foo,bar', 'GET');\n        $this->fractal->parseFractalIncludes($request);\n        $requestedIncludes = $this->fractal->getFractal()->getRequestedIncludes();\n\n        $this->assertEquals(['foo', 'bar'], $requestedIncludes);\n    }\n\n    public function testParseFractalIncludesWithSpaces()\n    {\n        $request = Request::create('/?include=foo, bar', 'GET');\n        $this->fractal->parseFractalIncludes($request);\n        $requestedIncludes = $this->fractal->getFractal()->getRequestedIncludes();\n\n        $this->assertEquals(['foo', 'bar'], $requestedIncludes);\n    }\n}\n"
  },
  {
    "path": "tests/Transformer/FactoryTest.php",
    "content": "<?php\n\nnamespace Dingo\\Api\\Tests\\Transformer;\n\nuse Dingo\\Api\\Tests\\BaseTestCase;\nuse Dingo\\Api\\Tests\\Stubs\\TransformerStub;\nuse Dingo\\Api\\Tests\\Stubs\\UserStub;\nuse Dingo\\Api\\Tests\\Stubs\\UserTransformerStub;\nuse Dingo\\Api\\Transformer\\Factory;\nuse Illuminate\\Container\\Container;\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Support\\Collection;\nuse Mockery;\n\nclass FactoryTest extends BaseTestCase\n{\n    /**\n     * @var Factory\n     */\n    protected $factory;\n\n    public function setUp(): void\n    {\n        $container = new Container;\n        $container['request'] = Mockery::mock(\\Dingo\\Api\\Http\\Request::class);\n\n        $this->factory = new Factory($container, new TransformerStub);\n    }\n\n    public function testResponseIsTransformable()\n    {\n        $this->assertFalse($this->factory->transformableResponse(new UserStub('Jason'), new UserTransformerStub));\n\n        $this->factory->register(UserStub::class, new UserTransformerStub);\n\n        $this->assertTrue($this->factory->transformableResponse(new UserStub('Jason'), new UserTransformerStub));\n    }\n\n    public function testRegisterParameterOrder()\n    {\n        // Third parameter is parameters and fourth is callback.\n        $binding = $this->factory->register(UserStub::class, new UserTransformerStub,\n            ['foo' => 'bar'], function ($foo) {\n                $this->assertSame('foo', $foo);\n            });\n\n        $binding->fireCallback('foo');\n        $this->assertSame(['foo' => 'bar'], $binding->getParameters());\n\n        // Third parameter is parameters and fourth is null.\n        $binding = $this->factory->register(UserStub::class, new UserTransformerStub,\n            ['foo' => 'bar']);\n\n        $this->assertSame(['foo' => 'bar'], $binding->getParameters());\n\n        // Third parameter is an empty array and fourth is callback.\n        $binding = $this->factory->register(UserStub::class, new UserTransformerStub, [],\n            function ($foo) {\n                $this->assertSame('foo', $foo);\n            });\n\n        $binding->fireCallback('foo');\n    }\n\n    public function testResponseIsTransformableType()\n    {\n        $this->assertFalse($this->factory->transformableType(['foo' => 'bar']));\n        $this->assertTrue($this->factory->transformableType('Foo'));\n        $this->assertTrue($this->factory->transformableType((object) ['foo' => 'bar']));\n    }\n\n    public function testTransformingResponse()\n    {\n        $this->factory->register(UserStub::class, new UserTransformerStub);\n\n        $response = $this->factory->transform(new UserStub('Jason'));\n\n        $this->assertSame(['name' => 'Jason'], $response);\n    }\n\n    public function testTransformingCollectionResponse()\n    {\n        $this->factory->register(UserStub::class, new UserTransformerStub);\n\n        $response = $this->factory->transform(new Collection([new UserStub('Jason'), new UserStub('Bob')]));\n\n        $this->assertSame([['name' => 'Jason'], ['name' => 'Bob']], $response);\n    }\n\n    public function testTransforingWithIlluminateRequest()\n    {\n        $container = new Container;\n        $container['request'] = new Request();\n\n        $factory = new Factory($container, new TransformerStub);\n\n        $factory->register(UserStub::class, new UserTransformerStub);\n\n        $response = $factory->transform(new UserStub('Jason'));\n\n        $this->assertSame(['name' => 'Jason'], $response);\n    }\n\n    public function testTransformingWithNoTransformerThrowsException()\n    {\n        $this->expectException(\\RuntimeException::class);\n        $this->expectExceptionMessage('Unable to find bound transformer for \"Dingo\\Api\\Tests\\Stubs\\UserStub\" class');\n\n        $this->factory->transform(new UserStub('Jason'));\n    }\n}\n"
  }
]