[
  {
    "path": ".editorconfig",
    "content": "; This file is for unifying the coding style for different editors and IDEs.\n; More information at http://editorconfig.org\n\nroot = true\n\n[*]\ncharset = utf-8\nindent_size = 4\nindent_style = space\nend_of_line = lf\ninsert_final_newline = true\ntrim_trailing_whitespace = true\n\n[*.md]\ntrim_trailing_whitespace = false\n"
  },
  {
    "path": ".gitattributes",
    "content": "# Path-based git attributes\n# https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html\n\n# Ignore all test and documentation with \"export-ignore\".\n/.gitattributes     export-ignore\n/.gitignore         export-ignore\n/.travis.yml        export-ignore\n/phpunit.xml.dist   export-ignore\n/.scrutinizer.yml   export-ignore\n/tests              export-ignore\n/.editorconfig      export-ignore\n/.github            export-ignore\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "# Help me support this package\n\nko_fi: DarkGhostHunter\ncustom: ['https://paypal.me/darkghosthunter']\n"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "version: 2\nupdates:\n- package-ecosystem: composer\n  directory: \"/\"\n  schedule:\n    interval: daily\n    time: \"09:00\"\n  open-pull-requests-limit: 10\n"
  },
  {
    "path": ".github/workflows/php.yml",
    "content": "name: PHP Composer\n\non:\n  push:\n  pull_request:\n\njobs:\n  test:\n\n    runs-on: ubuntu-latest\n    strategy:\n      fail-fast: true\n      matrix:\n        php: [8.0, 7.4]\n        laravel: [8.*, 7.*, 6.*]\n        dependency-version: [prefer-stable, prefer-lowest]\n        include:\n          - laravel: 8.*\n            testbench: 6.*\n          - laravel: 7.*\n            testbench: 5.*\n          - laravel: 6.*\n            testbench: ^4.1\n\n    name: PHP ${{ matrix.php }} - Laravel ${{ matrix.laravel }} - ${{ matrix.dependency-version }}\n\n    steps:\n    - name: Checkout\n      uses: actions/checkout@v2\n\n    - name: Setup PHP\n      uses: shivammathur/setup-php@v2\n      with:\n        php-version: ${{ matrix.php }}\n        extensions: mbstring, intl\n        coverage: xdebug\n\n    - name: Cache dependencies\n      uses: actions/cache@v2\n      with:\n        path: ~/.composer/cache/files\n        key: ${{ runner.os }}-laravel-${{ matrix.laravel }}-php-${{ matrix.php }}-composer-${{ hashFiles('composer.json') }}\n        restore-keys: ${{ runner.os }}-laravel-${{ matrix.laravel }}-php-${{ matrix.php }}-composer-\n\n    - name: Install dependencies\n      run: |\n          composer require \"laravel/framework:${{ matrix.laravel }}\" \"orchestra/testbench:${{ matrix.testbench }}\" --no-progress --no-update\n          composer update --${{ matrix.dependency-version }} --prefer-dist --no-progress --no-suggest\n\n    - name: Run Tests\n      run: composer run-script test\n\n    - name: Upload Coverage to Coveralls\n      env:\n        COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n        COVERALLS_SERVICE_NAME: github\n      run: |\n          rm -rf composer.* vendor/\n          composer require php-coveralls/php-coveralls\n          vendor/bin/php-coveralls\n"
  },
  {
    "path": ".gitignore",
    "content": "build\ncomposer.lock\ndocs\nvendor\ncoverage\n.idea"
  },
  {
    "path": ".styleci.yml",
    "content": "preset: laravel\n\ndisabled:\n  - single_class_element_per_statement\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) Italo Israel Baeza Cabrera\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE."
  },
  {
    "path": "README.md",
    "content": "## This package has been superseeded by [Laragear/Preload](https://github.com/Laragear/Preload).\n\nPlease migrate to the new package.\n\n---\n\n# Laraload\n\nEffortlessly create a PHP Preload Script for your Laravel project.\n\n## Requirements\n\n* Laravel 6.x, 7.x or 8.x (Lumen _may_ work too)\n* PHP 7.4.3, PHP 8.0 or later\n* `ext-opcache`\n\n> The Opcache extension is not enforced by the package. Just be sure to enable it in your project's PHP main process.\n\n## Installation\n\nCall composer and you're done.\n\n```bash\ncomposer require darkghosthunter/laraload\n```\n\n## What is Preloading? What does this?\n\nPreloading is a new feature for PHP. It \"compiles\" a list of files into memory, thus making the application code _fast_ without warming up. For that to work, it needs to read a PHP script that \"uploads\" these files into memory, at process startup.\n\nThis allows the first Requests to avoid cold starts, where all the scripts must be loaded by PHP at that moment. Since this step is moved to the process startup, first Requests become _faster_ as all needed scripts are already in memory.\n\nThis package wraps the Preloader package that generates a preload file. Once it's generated, you can point the generated list into your `php.ini`:\n\n```ini\nopcache.preload = 'www/app/storage/preload.php';\n```\n\nAfter that, the next time PHP starts, this list of files will be preloaded.\n\n## Usage\n\nBy default, this package constantly recreates your preload script each 500 requests in `storage/preload.php`. That's it. But you want the details, don't you?\n\n1. A global terminable middleware checks for non-error response.\n2. Then it calls a custom *Condition* class.\n3. If the *Condition* evaluates to `true`, the Preload Script is generated.\n4. A `PreloadCalledEvent` is fired with the generation status.\n\n## Configuration\n\nSome people may not be happy with the \"default\" behaviour. Luckily, you can configure your own way to generate the script.\n\nFirst publish the configuration file:\n\n```bash\nphp artisan vendor:publish --provider=\"DarkGhostHunter\\Laraload\\LaraloadServiceProvider\"\n```\n\nLet's check the config array:\n\n```php\n<?php\n\nreturn [\n    'enable' => env('LARALOAD_ENABLE'),\n    'condition' => \\DarkGhostHunter\\Laraload\\Conditions\\CountRequests::class,\n    'output' =>  storage_path('preload.php'),\n    'memory' => 32,\n    'use_require' => false,\n    'autoload' => base_path('vendor/autoload.php'),\n    'ignore-not-found' => true,\n];\n```\n\n#### Enable\n\n```php\n<?php\n\nreturn [\n    'enable' => env('LARALOAD_ENABLE'),\n];\n```\n\nBy default, Laraload will be automatically enabled on production environments. You can forcefully enable or disable it using an environment variable set to `true` or `false`, respectively.\n\n```dotenv\nLARALOAD_ENABLE=true\n```\n\n#### Condition\n\n```php\n<?php\n\nreturn [\n    'condition' => 'App\\MyCustomCondition@handle',\n];\n```\n\nThis package comes with a _simple_ condition class that returns `true` every 500 requests, which triggers the script generation. \n\nYou can define your own condition class to generate the Preload script. This will be called after the request is handled to the browser, and it will be resolved by the Service Container.\n\nThe condition is called the same way as a Controller action: as an invokable class or using _Class@action_ notation.\n\n#### Output\n\n```php\n<?php\n\nreturn [\n    'output' => '/var/www/preloads/my_preload.php',\n];\n```\n \nBy default, the script is saved in your storage path, but you can change the filename and path to save it as long PHP has permissions to write on it. Double-check your file permissions.\n\n#### Memory Limit\n\n```php\n<?php\n\nreturn [\n    'memory' => 64,\n];\n```\n\nFor most applications, 32MB is fine as a preload limit, but you may fine-tune it for your project specifically.\n\n#### Method\n\n```php\n<?php\n\nreturn [\n    'use_require' => true,\n    'autoload' => base_path('vendor/autoload.php'),\n];\n```\n\nOpcache allows to preload files using `require_once` or `opcache_compile_file()`.\n\nLaraload uses `opcache_compile_file()` for better manageability on the files preloaded. Some unresolved links may output warnings at startup, but nothing critical.\n\nUsing `require_once` will \"execute\" all files, resolving all the links (imports, parent classes, traits, interfaces, etc.) before compiling it, and may output heavy errors on files that shouldn't be executed. Depending on your application, you may want to use one over the other.\n\nIf you plan use `require_once`, ensure you have set the correct path to the Composer Autoloader, since it will be used to resolve classes, among other files.\n\n### Ignore not found files\n\n```php\n<?php\n\nreturn [\n    'ignore-not-found' => true,\n];\n```\n\nVersion 2.1.0 and onward ignores non-existent files by default. This may work for files created by Laravel at runtime and actively cached by Opcache, but that on deployment are absent, like [real-time facades](https://laravel.com/docs/facades#real-time-facades).\n\nYou can disable this for any reason, which will throw an Exception if any file is missing, but is recommended leaving it alone unless you know what you're doing. \n\n### Include & Exclude directories\n\nFor better manageability, you can now append or exclude files from directories using the [Symfony Finder](https://symfony.com/doc/current/components/finder.html), which is included in this package, to retrieve a list of files inside of them with better filtering options.\n\nTo do so, add an `array` of directories, or register a callback receiving a Symfony Finder instance to further filter which files you want to append or exclude. You can do this in your App Service Provider by using the `Laravel` facade (or injecting Laraload).\n\n```php\n\nuse Symfony\\Component\\Finder\\Finder;\nuse Illuminate\\Support\\ServiceProvider;\nuse DarkGhostHunter\\Laraload\\Facades\\Laraload;\n\nclass AppServiceProvider extends ServiceProvider\n{\n    // ...\n    \n    public function boot()\n    {\n        Laraload::append(function (Finder $find) {\n            $find->in('www/app/vendor/name/package/src')->name('*.php');\n        });\n        \n        Laraload::exclude(function (Finder $find) {\n            $find->in('www/app/resources/views')->name('*.blade.php');\n        });\n    }\n}\n```\n\n### FAQ\n\n* **Can I disable Laraload?**\n\n[Yes.](#enable)\n\n* **Do I need to restart my PHP Server to pick up the changes?**\n\nAbsolutely. Generating the script is not enough, PHP won't pick up the changes if the script path is empty or the PHP process itself is not restarted **completely**. You can schedule a server restart with CRON or something.\n\n* **The package returns errors when I used it!**\n  \nCheck you're using the latest PHP stable version (critical), and Opcache is enabled. Also, check your storage directory is writable.\n\nAs a safe-bet, you can use the safe preloader script in `darkghosthunter/preloader/helpers/safe-preloader.php` and debug the error.\n\nIf you're sure this is an error by the package, [open an issue](https://github.com/DarkGhostHunter/Laraload/issues/new) with full details and stack trace. If it's a problem on the Preloader itself, [issue it there](https://github.com/DarkGhostHunter/Preloader/issues).\n\n* **Why I can't use something like `php artisan laraload:generate` instead? Like a [Listener](https://laravel.com/docs/events) or [Scheduler](https://laravel.com/docs/scheduling)?**\n\nOpcache is not enabled when using PHP CLI, and if it is, it will gather wrong statistics. You must let the live application generate the list automatically _on demand_.\n\n* **Does this excludes the package itself from the list?**\n\nIt does not: since the underlying Preloader package may be not heavily requested, it doesn't matter if its excluded or not. The files in Laraload are also not excluded from the list, since these are needed to trigger the Preloader itself without hindering performance. \n\n* **I activated Laraload but my application still doesn't feel _fast_. What's wrong?**\n\nLaraload creates a preloading script, but **doesn't load the script into Opcache**. Once the script is generated, you must include it in your `php.ini` - currently there is no other way to do it. This will take effect only at PHP process startup.\n\nIf you still _feel_ your app is slow, remember to benchmark your app, cache your config and views, check your database queries and API calls, and queue expensive logic, among other things. You can also use [Laravel Octane](https://github.com/laravel/octane) on [RoadRunner](https://roadrunner.dev/).\n\n* **How the list is created?**\n\nBasically: the most hit files in descending order. Each file consumes memory, so the list is _soft-cut_ when the files reach a given memory limit (32MB by default).\n\n* **You said \"_soft-cut_\", why is that?**\n\nEach file is loaded using `opcache_compile_file()`. If the last file is a class with links outside the list, PHP will issue some warnings, which is normal and intended, but it won't compile the linked files if these were not added before. \n\n* **Can I just put all the files in my project?**\n\nYou shouldn't. Including all the files of your application may have diminishing returns compared to, for example, only the most requested. You can always benchmark your app yourself to prove this is wrong for your exclusive case.\n\n* **Can I use a Closure for my condition?**\n\nNo, you must use your default condition class or your own class, or use `Class@method` notation.\n\n* **Can I deactivate the middleware? Or check only XXX status?**\n\nNope. If you are looking for total control, [use directly the Preloader package](https://github.com/DarkGhostHunter/Preloader/).\n\n* **Does the middleware works on unit testing?**\n\nNope. The middleware is not registered if the application is running under Unit Testing environment.\n\n* **How can I know when a Preload script is successfully generated?**\n\nWhen the Preload script is called, you will receive a `PreloadCalledEvent` instance with the compilation status (`true` on success, `false` on failure). You can [add a Listener](https://laravel.com/docs/events#registering-events-and-listeners) to dispatch an email or a Slack notification.\n\nIf there is a bigger problem, your application logger will catch the exception.\n\n* **Why now I need to use a callback to append/exclude files, instead of a simple array of files?**\n\nThis new version uses Preloader 2, which offers greater flexibility to handle files inside a directory. This approach is incompatible with just issuing directly an array of files, but is more convenient in the long term. Considering that appending and excluding files mostly requires pin-point precision, it was decided to leave it as method calls for this kind of flexibility.\n\n* **How can I change the number of hits, cache or cache key for the default condition?**\n\nWhile I encourage you to create your own condition, you can easily change them by adding a [container event](https://laravel.com/docs/8.x/container#container-events) to your `AppServiceProvider.php`, under the `register()` method.\n\n```php\n$this->app->when(\\DarkGhostHunter\\Laraload\\Conditions\\CountRequests::class)\n     ->needs('$hits')\n     ->give(1500);\n```\n\n## License\n\nThis package is licenced by the [MIT License](LICENSE).\n"
  },
  {
    "path": "composer.json",
    "content": "{\n    \"name\": \"darkghosthunter/laraload\",\n    \"description\": \"Effortlessly make a Preload script for your Laravel application.\",\n    \"keywords\": [\n        \"darkghosthunter\",\n        \"laraload\"\n    ],\n    \"homepage\": \"https://github.com/darkghosthunter/laraload\",\n    \"license\": \"MIT\",\n    \"type\": \"library\",\n    \"authors\": [\n        {\n            \"name\": \"Italo Israel Baeza Cabrera\",\n            \"email\": \"darkghosthunter@gmail.com\",\n            \"role\": \"Developer\"\n        }\n    ],\n    \"require\": {\n        \"php\": \"^7.4.3||^8.0.2\",\n        \"illuminate/support\": \"^6.0||^7.0||^8.0\",\n        \"illuminate/http\": \"^6.0||^7.0||^8.0\",\n        \"illuminate/events\": \"^6.0||^7.0||^8.0\",\n        \"darkghosthunter/preloader\": \"^2.2.0\",\n        \"symfony/finder\": \"^4.3||^5.0\"\n    },\n    \"require-dev\": {\n        \"orchestra/testbench\": \"^4.1||^5.0||^6.0\",\n        \"phpunit/phpunit\": \"^9.3\",\n        \"mockery/mockery\": \"^1.4\",\n        \"orchestra/canvas\": \"^4.0||^5.0||^6.0\"\n    },\n    \"autoload\": {\n        \"psr-4\": {\n            \"DarkGhostHunter\\\\Laraload\\\\\": \"src\"\n        }\n    },\n    \"autoload-dev\": {\n        \"psr-4\": {\n            \"Tests\\\\\": \"tests\"\n        }\n    },\n    \"scripts\": {\n        \"test\": \"vendor/bin/phpunit --coverage-clover build/logs/clover.xml\",\n        \"test-coverage\": \"vendor/bin/phpunit --coverage-html coverage\"\n    },\n    \"config\": {\n        \"sort-packages\": true\n    },\n    \"extra\": {\n        \"laravel\": {\n            \"providers\": [\n                \"DarkGhostHunter\\\\Laraload\\\\LaraloadServiceProvider\"\n            ],\n            \"aliases\": {\n                \"Laraload\": \"DarkGhostHunter\\\\Laraload\\\\Facades\\\\Laraload\"\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "config/laraload.php",
    "content": "<?php\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | Main Switch\n    |--------------------------------------------------------------------------\n    |\n    | Laraload detects if the environment is production and automatically runs\n    | when under it. You can forcefully disable o enable it. Laraload doesn't\n    | runs if your app is running unit tests, don't worry about disabling it.\n    |\n    | Supported: \"null\", \"true\", \"false\".\n    |\n    */\n\n    'enable' => env('LARALOAD_ENABLE'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Condition logic\n    |--------------------------------------------------------------------------\n    |\n    | The custom condition logic you want to execute to generate (or not) the\n    | Preload script. You can use any class using it's name, or Class@method\n    | notation. This will be executed using the Service Container's \"call\".\n    |\n    */\n\n    'condition' => \\DarkGhostHunter\\Laraload\\Conditions\\CountRequests::class,\n\n    /*\n    |--------------------------------------------------------------------------\n    | Output\n    |--------------------------------------------------------------------------\n    |\n    | Once the Preload script is generated, it will written to the storage\n    | path of your application, since it should have permission to write.\n    | You can change the script output for anything as long is writable.\n    |\n    */\n\n    'output' => storage_path('preload.php'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Memory Limit\n    |--------------------------------------------------------------------------\n    |\n    | The Preloader script can be configured to handle a limited number of\n    | files based on their memory consumption. The default is a safe bet\n    | for most apps, but you can change it for your app specifically.\n    |\n    */\n\n    'memory' => 32,\n\n    /*\n    |--------------------------------------------------------------------------\n    | Upload method\n    |--------------------------------------------------------------------------\n    |\n    | Opcache supports preloading files by using `require_once` (which executes\n    | and resolves each file link), and `opcache_compile_file` (which not). If\n    | you want to use require ensure the Composer Autoloader path is correct.\n    |\n    */\n\n    'use_require' => false,\n    'autoload'    => base_path('vendor/autoload.php'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Ignore Not Found\n    |--------------------------------------------------------------------------\n    |\n    | Sometimes Opcache will include in the list files that are generated by\n    | Laravel at runtime which don't exist when deploying the application.\n    | To avoid errors on preloads, we can tell Preloader to ignore them.\n    |\n    */\n\n    'ignore-not-found' => true,\n\n];\n"
  },
  {
    "path": "phpunit.xml.dist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<phpunit bootstrap=\"vendor/autoload.php\"\n         backupGlobals=\"false\"\n         backupStaticAttributes=\"false\"\n         colors=\"true\"\n         verbose=\"true\"\n         convertErrorsToExceptions=\"true\"\n         convertNoticesToExceptions=\"true\"\n         convertWarningsToExceptions=\"true\"\n         processIsolation=\"false\"\n         stopOnFailure=\"false\">\n    <testsuites>\n        <testsuite name=\"Test Suite\">\n            <directory>tests</directory>\n        </testsuite>\n    </testsuites>\n    <filter>\n        <whitelist>\n            <directory suffix=\".php\">src/</directory>\n            <exclude>\n                <file>src/LaraloadServiceProvider.php</file>\n            </exclude>\n        </whitelist>\n    </filter>\n    <logging>\n        <log type=\"tap\" target=\"build/report.tap\"/>\n        <log type=\"junit\" target=\"build/report.junit.xml\"/>\n        <log type=\"coverage-html\" target=\"build/coverage\" charset=\"UTF-8\" yui=\"true\" highlight=\"true\"/>\n        <log type=\"coverage-text\" target=\"build/coverage.txt\"/>\n        <log type=\"coverage-clover\" target=\"build/logs/clover.xml\"/>\n    </logging>\n</phpunit>\n"
  },
  {
    "path": "src/Conditions/CountRequests.php",
    "content": "<?php\n\nnamespace DarkGhostHunter\\Laraload\\Conditions;\n\nuse Illuminate\\Contracts\\Cache\\Repository as Cache;\n\nclass CountRequests\n{\n    /**\n     * Cache repository\n     *\n     * @var \\Illuminate\\Contracts\\Cache\\Repository\n     */\n    protected Cache $cache;\n\n    /**\n     * Number of hits to\n     *\n     * @var int\n     */\n    protected int $hits;\n\n    /**\n     * @var string\n     */\n    protected string $cacheKey;\n\n    /**\n     * CountRequest constructor.\n     *\n     * @param  \\Illuminate\\Contracts\\Cache\\Repository  $cache\n     * @param  int  $hits\n     * @param  string  $cacheKey\n     */\n    public function __construct(Cache $cache, int $hits = 500, string $cacheKey = 'laraload|request_hits')\n    {\n        $this->cache = $cache;\n        $this->hits = $hits;\n        $this->cacheKey = $cacheKey;\n    }\n\n    /**\n     * Recreates the Preload script each given number of requests.\n     *\n     * @return bool\n     */\n    public function __invoke(): bool\n    {\n        // Increment the count by one. If it doesn't exists, we will start with 1.\n        $count = $this->cache->increment($this->cacheKey);\n\n        // Each number of hits return true\n        if ($count && $count % $this->hits === 0) {\n            $this->cache->set($this->cacheKey, 0);\n            return true;\n        }\n\n        return false;\n    }\n}\n"
  },
  {
    "path": "src/Events/PreloadCalledEvent.php",
    "content": "<?php\n\nnamespace DarkGhostHunter\\Laraload\\Events;\n\nclass PreloadCalledEvent\n{\n    /**\n     * Generation status\n     *\n     * @var bool true on success, false on failure\n     */\n    public bool $success;\n\n    /**\n     * PreloadCalledEvent constructor.\n     *\n     * @param  bool  $success\n     */\n    public function __construct(bool $success)\n    {\n        $this->success = $success;\n    }\n}\n"
  },
  {
    "path": "src/Facades/Laraload.php",
    "content": "<?php\n\nnamespace DarkGhostHunter\\Laraload\\Facades;\n\nuse Illuminate\\Support\\Facades\\Facade;\n\n/**\n * @method static void append(array|string|callable $directories)\n * @method static void exclude(array|string|callable $directories)\n * @method static bool generate()\n */\nclass Laraload extends Facade\n{\n    /**\n     * @inheritDoc\n     */\n    protected static function getFacadeAccessor()\n    {\n        return \\DarkGhostHunter\\Laraload\\Laraload::class;\n    }\n}\n"
  },
  {
    "path": "src/Http/Middleware/LaraloadMiddleware.php",
    "content": "<?php\n\nnamespace DarkGhostHunter\\Laraload\\Http\\Middleware;\n\nuse Closure;\nuse DarkGhostHunter\\Laraload\\Laraload;\nuse Illuminate\\Config\\Repository as Config;\nuse Illuminate\\Container\\Container;\n\nclass LaraloadMiddleware\n{\n    /**\n     * @var \\Illuminate\\Config\\Repository\n     */\n    protected Config $config;\n\n    /**\n     * Application container instance.\n     *\n     * @var \\Illuminate\\Container\\Container\n     */\n    protected Container $container;\n\n    /**\n     * CountRequest constructor.\n     *\n     * @param  \\Illuminate\\Config\\Repository  $config\n     */\n    public function __construct(Config $config)\n    {\n        $this->container = Container::getInstance();\n        $this->config = $config;\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        return $next($request);\n    }\n\n    /**\n     * Perform any final actions for the request lifecycle.\n     *\n     * @param  \\Symfony\\Component\\HttpFoundation\\Request  $request\n     * @param  \\Symfony\\Component\\HttpFoundation\\Response  $response\n     *\n     * @return void\n     * @throws \\Illuminate\\Contracts\\Container\\BindingResolutionException\n     */\n    public function terminate($request, $response)\n    {\n        if ($this->responseNotError($response) && $this->conditionIsTrue()) {\n            $this->container->make(Laraload::class)->generate();\n        }\n    }\n\n    /**\n     * Returns if the Response is anything but an error or an invalid response.\n     *\n     * @param  \\Psr\\Http\\Message\\ResponseInterface|\\Symfony\\Component\\HttpFoundation\\Response  $response\n     *\n     * @return bool\n     */\n    protected function responseNotError($response): bool\n    {\n        return $response->getStatusCode() < 400;\n    }\n\n    /**\n     * Checks if the given condition logic is true or false.\n     *\n     * @return bool\n     */\n    protected function conditionIsTrue(): bool\n    {\n        return (bool)$this->container->call($this->config->get('laraload.condition'), [], '__invoke');\n    }\n}\n"
  },
  {
    "path": "src/Laraload.php",
    "content": "<?php\n\nnamespace DarkGhostHunter\\Laraload;\n\nuse DarkGhostHunter\\Preloader\\Preloader;\nuse Illuminate\\Contracts\\Events\\Dispatcher;\nuse Illuminate\\Contracts\\Config\\Repository as Config;\n\nclass Laraload\n{\n    /**\n     * Configuration array.\n     *\n     * @var array\n     */\n    protected array $config;\n\n    /**\n     * Preloader instance.\n     *\n     * @var \\DarkGhostHunter\\Preloader\\Preloader\n     */\n    protected Preloader $preloader;\n\n    /**\n     * Event Dispatcher.\n     *\n     * @var \\Illuminate\\Contracts\\Events\\Dispatcher\n     */\n    protected Dispatcher $dispatcher;\n\n    /**\n     * Callback to use to append files.\n     *\n     * @var callable\n     */\n    protected $append;\n\n    /**\n     * Callback to use to exclude files.\n     *\n     * @var callable\n     */\n    protected $exclude;\n\n    /**\n     * Laraload constructor.\n     *\n     * @param  \\Illuminate\\Contracts\\Config\\Repository $config\n     * @param  \\Illuminate\\Contracts\\Events\\Dispatcher $dispatcher\n     * @param  \\DarkGhostHunter\\Preloader\\Preloader $preloader\n     */\n    public function __construct(Config $config, Dispatcher $dispatcher, Preloader $preloader)\n    {\n        $this->config = $config->get('laraload');\n        $this->preloader = $preloader;\n        $this->dispatcher = $dispatcher;\n    }\n\n    /**\n     * Registers a callback to use to append files to the Preloader.\n     *\n     * @param  array|string|callable  $append\n     *\n     * @return void\n     */\n    public function append($append): void\n    {\n        $this->append = $append;\n    }\n\n    /**\n     * Registers a callback to use to exclude files from the Preloader.\n     *\n     * @param  array|string|callable  $exclude\n     *\n     * @return void\n     */\n    public function exclude($exclude): void\n    {\n        $this->exclude = $exclude;\n    }\n\n    /**\n     * Generates the Preloader Script.\n     *\n     * @return bool\n     */\n    public function generate(): bool\n    {\n        $preloader = $this->preloader\n            ->ignoreNotFound($this->config['ignore-not-found'])\n            ->memoryLimit($this->config['memory'])\n            ->exclude($this->exclude)\n            ->append($this->append);\n\n        if ($this->config['use_require']) {\n            $preloader->useRequire($this->config['autoload']);\n        }\n\n        $this->dispatcher->dispatch(new Events\\PreloadCalledEvent(\n            $result = $preloader->writeTo($this->config['output'])\n        ));\n\n        return $result;\n    }\n}\n"
  },
  {
    "path": "src/LaraloadServiceProvider.php",
    "content": "<?php\n\nnamespace DarkGhostHunter\\Laraload;\n\nuse Illuminate\\Config\\Repository;\nuse Illuminate\\Contracts\\Http\\Kernel;\nuse Illuminate\\Support\\ServiceProvider;\nuse DarkGhostHunter\\Preloader\\Preloader;\nuse DarkGhostHunter\\Laraload\\Http\\Middleware\\LaraloadMiddleware;\n\nclass LaraloadServiceProvider extends ServiceProvider\n{\n    /**\n     * Register the application services.\n     *\n     * @return void\n     */\n    public function register()\n    {\n        $this->mergeConfigFrom(__DIR__ . '/../config/laraload.php', 'laraload');\n\n        $this->app->singleton(Preloader::class, fn() => Preloader::make());\n        $this->app->singleton(Laraload::class);\n    }\n\n    /**\n     * Bootstrap the application services.\n     *\n     * @param  \\Illuminate\\Config\\Repository  $config\n     * @param  \\Illuminate\\Contracts\\Http\\Kernel  $kernel\n     *\n     * @return void\n     */\n    public function boot(Repository $config, Kernel $kernel)\n    {\n        // We will only register the middleware if not Running Unit Tests\n        if ($this->shouldRun($config)) {\n            $kernel->pushMiddleware(LaraloadMiddleware::class);\n        }\n\n        if ($this->app->runningInConsole()) {\n            $this->publishes([__DIR__ . '/../config/laraload.php' => config_path('laraload.php')], 'config');\n        }\n    }\n\n    /**\n     * Checks if Laraload should run.\n     *\n     * @param  \\Illuminate\\Config\\Repository  $config\n     *\n     * @return bool\n     *\n     * @codeCoverageIgnore\n     */\n    protected function shouldRun(Repository $config): bool\n    {\n        // If it's null run only on production, otherwise the developer decides.\n        return $config->get('laraload.enable') ?? $this->app->environment('production');\n    }\n}\n"
  },
  {
    "path": "tests/Conditions/CountRequestTest.php",
    "content": "<?php\n\nnamespace Tests\\Conditions;\n\nuse Exception;\nuse Illuminate\\Contracts\\Cache\\Repository;\nuse Orchestra\\Testbench\\TestCase;\nuse Tests\\Stubs\\ConditionCallable;\nuse Illuminate\\Contracts\\Http\\Kernel;\nuse Illuminate\\Support\\Facades\\Route;\nuse Illuminate\\Support\\Facades\\Event;\nuse DarkGhostHunter\\Laraload\\Laraload;\nuse DarkGhostHunter\\Preloader\\Preloader;\nuse DarkGhostHunter\\Laraload\\LaraloadServiceProvider;\nuse DarkGhostHunter\\Laraload\\Conditions\\CountRequests;\nuse DarkGhostHunter\\Laraload\\Events\\PreloadCalledEvent;\nuse DarkGhostHunter\\Laraload\\Facades\\Laraload as LaraloadFacade;\nuse DarkGhostHunter\\Laraload\\Http\\Middleware\\LaraloadMiddleware;\n\nclass CountRequestTest extends TestCase\n{\n    protected function getPackageProviders($app)\n    {\n        return [LaraloadServiceProvider::class];\n    }\n\n    protected function getPackageAliases($app)\n    {\n        return [\n            'Laraload' => LaraloadFacade::class\n        ];\n    }\n\n    public function testReaches500AndResets()\n    {\n        $cache = $this->mock(Repository::class);\n\n        $cache->shouldReceive('increment')->with('laraload|request_hits')\n            ->andReturn(500);\n\n        $cache->shouldReceive('set')->with('laraload|request_hits', 0)\n            ->andReturnNull();\n\n        (new CountRequests($cache))();\n    }\n\n    public function testUsesNonDefaultConfig()\n    {\n        $cache = $this->mock(Repository::class);\n\n        $cache->shouldReceive('increment')->with('foo')\n            ->andReturn(6000);\n\n        $cache->shouldReceive('set')->with('foo', 0)\n            ->andReturnNull();\n\n        (new CountRequests($cache, 6000, 'foo'))();\n    }\n}\n"
  },
  {
    "path": "tests/PackageTest.php",
    "content": "<?php\n\nnamespace Tests;\n\nuse Exception;\nuse Orchestra\\Testbench\\TestCase;\nuse Tests\\Stubs\\ConditionCallable;\nuse Illuminate\\Contracts\\Http\\Kernel;\nuse Illuminate\\Support\\Facades\\Route;\nuse Illuminate\\Support\\Facades\\Event;\nuse DarkGhostHunter\\Laraload\\Laraload;\nuse DarkGhostHunter\\Preloader\\Preloader;\nuse DarkGhostHunter\\Laraload\\LaraloadServiceProvider;\nuse DarkGhostHunter\\Laraload\\Conditions\\CountRequests;\nuse DarkGhostHunter\\Laraload\\Events\\PreloadCalledEvent;\nuse DarkGhostHunter\\Laraload\\Facades\\Laraload as LaraloadFacade;\nuse DarkGhostHunter\\Laraload\\Http\\Middleware\\LaraloadMiddleware;\n\nclass PackageTest extends TestCase\n{\n    protected function getPackageProviders($app)\n    {\n        return [LaraloadServiceProvider::class];\n    }\n\n    protected function getPackageAliases($app)\n    {\n        return [\n            'Laraload' => LaraloadFacade::class\n        ];\n    }\n\n    public function testPublishesConfig()\n    {\n        $this->artisan('vendor:publish', [\n            '--provider' => 'DarkGhostHunter\\Laraload\\LaraloadServiceProvider',\n        ])\n            ->execute();\n\n        $this->assertFileExists(base_path('config/laraload.php'));\n        $this->assertFileEquals(base_path('config/laraload.php'), __DIR__ . '/../config/laraload.php');\n\n        unlink(base_path('config/laraload.php'));\n    }\n\n    public function testDoesntRegisterTerminableMiddlewareInTesting()\n    {\n        $this->assertFalse(\n            $this->app[Kernel::class]->hasMiddleware(LaraloadMiddleware::class)\n        );\n    }\n\n    public function testDoesntWorkWithErrorResponse()\n    {\n        $condition = $this->mock(CountRequests::class);\n\n        $this->app[Kernel::class]->pushMiddleware(LaraloadMiddleware::class);\n\n        $condition->shouldNotReceive('__invoke');\n\n        Route::get('/test', function () {\n            throw new Exception;\n        });\n\n        $condition->shouldReceive('__invoke');\n\n        $this->get('/test')->assertStatus(500);\n    }\n\n    public function testReachesCallable()\n    {\n        $condition = $this->mock(CountRequests::class);\n        $laraload = $this->mock(Laraload::class);\n\n        $this->app[Kernel::class]->pushMiddleware(LaraloadMiddleware::class);\n\n        Route::get('/test', function () {\n            return 'ok';\n        });\n\n        $condition->shouldReceive('__invoke')\n            ->andReturnTrue();\n        $laraload->shouldReceive('generate')\n            ->andReturnTrue();\n\n        $this->get('/test')->assertSee('ok');\n    }\n\n    public function testCallableWithMethod()\n    {\n        $this->app[Kernel::class]->pushMiddleware(LaraloadMiddleware::class);\n\n        $laraload = $this->mock(Laraload::class);\n\n        $laraload->shouldReceive('generate')\n            ->andReturnTrue();\n\n        $this->app->make('config')->set('laraload.condition', ConditionCallable::class . '@handle');\n\n        Route::get('/test', function () {\n            return 'ok';\n        });\n\n        $this->get('/test')->assertSee('ok');\n\n        $this->assertEquals(true, ConditionCallable::$called);\n    }\n\n    public function testCallableWithMethodAndParameters()\n    {\n        $laraload = $this->mock(Laraload::class);\n\n        $this->app[Kernel::class]->pushMiddleware(LaraloadMiddleware::class);\n\n        $laraload->shouldReceive('generate')\n            ->andReturnTrue();\n\n        $this->app->make('config')->set(\n            'laraload.condition', ConditionCallable::class . '@handle');\n\n        Route::get('/test', function () {\n            return 'ok';\n        });\n\n        $this->get('/test')->assertSee('ok');\n\n        $this->assertTrue(ConditionCallable::$called);\n    }\n\n    public function testConditionWorks()\n    {\n        $condition = $this->mock(CountRequests::class);\n        $laraload = $this->mock(Laraload::class);\n\n        $this->app[Kernel::class]->pushMiddleware(LaraloadMiddleware::class);\n\n        $laraload->shouldReceive('generate')\n            ->andReturnTrue();\n\n        $condition->shouldReceive('__invoke')\n            ->withNoArgs()\n            ->andReturnTrue();\n\n        $this->app->make('config')->set('laraload.condition', CountRequests::class);\n\n        Route::get('/test', function () {\n            return 'ok';\n        });\n\n        $this->get('/test')->assertSee('ok');\n    }\n\n    public function testConditionsCallsLaraload()\n    {\n        $laraload = $this->mock(Laraload::class);\n\n        $this->app[Kernel::class]->pushMiddleware(LaraloadMiddleware::class);\n\n        $laraload->shouldReceive('generate');\n\n        $this->app->make('config')->set('laraload.condition', CountRequests::class);\n\n        Route::get('/test', function () {\n            return 'ok';\n        });\n\n        $this->get('/test')->assertSee('ok');\n    }\n\n    public function testLaraloadGeneratesScript()\n    {\n        $event = Event::fake();\n\n        $this->app[Kernel::class]->pushMiddleware(LaraloadMiddleware::class);\n\n        $preload = $this->mock(Preloader::class);\n\n        $preload->shouldReceive('ignoreNotFound')\n            ->with(true)\n            ->andReturnSelf();\n        $preload->shouldReceive('memoryLimit')\n            ->with(32)\n            ->andReturnSelf();\n        $preload->shouldReceive('exclude')\n            ->with([])\n            ->andReturnSelf();\n        $preload->shouldReceive('append')\n            ->with([])\n            ->andReturnSelf();\n        $preload->shouldReceive('writeTo')\n            ->with(config('laraload.output'))\n            ->andReturnTrue();\n\n        $this->app->when(CountRequests::class)\n            ->needs('$hits')\n            ->give(1);\n\n        $this->app->make('config')->set('laraload.condition', CountRequests::class);\n\n        Route::get('/test', function () {\n            return 'ok';\n        });\n\n        $this->get('/test')->assertSee('ok');\n\n        $event->assertDispatched(PreloadCalledEvent::class, function ($event) {\n            return $event->success;\n        });\n    }\n\n    public function testUsesRequireInsteadOfCompile()\n    {\n        $this->app->when(CountRequests::class)\n            ->needs('$hits')\n            ->give(1);\n\n        $this->app->make('config')->set('laraload.use_require', true);\n        $this->app->make('config')->set('laraload.condition', CountRequests::class);\n\n        $preloader = $this->mock(Preloader::class);\n\n        $preloader->shouldReceive('ignoreNotFound')->andReturnSelf();\n        $preloader->shouldReceive('memoryLimit')->andReturnSelf();\n        $preloader->shouldReceive('exclude')->andReturnSelf();\n        $preloader->shouldReceive('append')->andReturnSelf();\n        $preloader->shouldReceive('useRequire')->with(config('laraload.autoload'))->andReturnSelf();\n        $preloader->shouldReceive('writeTo')->with(config('laraload.output'))->andReturnTrue();\n\n        $this->app[Kernel::class]->pushMiddleware(LaraloadMiddleware::class);\n\n        Route::get('/test', fn() => response('ok'));\n        $this->get('/test')->assertStatus(200);\n    }\n\n    public function testReceivesAppendedAndExcludedFiles()\n    {\n        $this->app->when(CountRequests::class)\n            ->needs('$hits')\n            ->give(1);\n\n        $this->app->make('config')->set('laraload.condition', CountRequests::class);\n\n        $preloader = $this->mock(Preloader::class);\n\n        $preloader->shouldReceive('ignoreNotFound')->andReturnSelf();\n        $preloader->shouldReceive('memoryLimit')->andReturnSelf();\n        $preloader->shouldReceive('exclude')->with('foo')->andReturnSelf();\n        $preloader->shouldReceive('append')->with('bar')->andReturnSelf();\n        $preloader->shouldReceive('writeTo')->with(config('laraload.output'))->andReturnTrue();\n\n        LaraloadFacade::exclude('foo');\n        LaraloadFacade::append('bar');\n\n        $this->app[Kernel::class]->pushMiddleware(LaraloadMiddleware::class);\n\n        Route::get('/test', fn() => response('ok'));\n        $this->get('/test')->assertStatus(200);\n    }\n\n    public function testWorksOnNonErrorCodes()\n    {\n        $laraload = $this->mock(Laraload::class);\n\n        $this->app->when(CountRequests::class)\n            ->needs('$hits')\n            ->give(1);\n        $laraload->shouldReceive('generate')->times(3);\n\n        $this->app->make('config')->set('laraload.condition', CountRequests::class);\n        $this->app[Kernel::class]->pushMiddleware(LaraloadMiddleware::class);\n\n        $i = rand(100, 199);\n        Route::get('/100', fn() => response('ok', $i));\n        $this->get('/100')->assertStatus($i);\n\n        $i = rand(200, 299);\n        Route::get('/200', fn() => response('ok', $i));\n        $this->get('/200')->assertStatus($i);\n\n        $i = rand(300, 399);\n        Route::get('/300', fn() => response('ok', $i));\n        $this->get('/300')->assertStatus($i);\n\n        $i = rand(400, 499);\n        Route::get('/400', fn() => response('ok', $i));\n        $this->get('/400')->assertStatus($i);\n\n        $i = rand(500, 599);\n        Route::get('/500', fn() => response('ok', $i));\n        $this->get('/500')->assertStatus($i);\n    }\n\n    public function testReceivesFalseForIgnoringNotFoundFiles()\n    {\n        $this->app->when(CountRequests::class)\n            ->needs('$hits')\n            ->give(1);\n\n        $this->app->make('config')->set('laraload.condition', CountRequests::class);\n        $this->app->make('config')->set('laraload.ignore-not-found', false);\n\n        $preloader = $this->mock(Preloader::class);\n\n        $preloader->shouldReceive('ignoreNotFound')->with(false)->andReturnSelf();\n        $preloader->shouldReceive('memoryLimit')->andReturnSelf();\n        $preloader->shouldReceive('exclude')->with(null)->andReturnSelf();\n        $preloader->shouldReceive('append')->with(null)->andReturnSelf();\n        $preloader->shouldReceive('writeTo')->with(config('laraload.output'))->andReturnTrue();\n\n        $this->app[Kernel::class]->pushMiddleware(LaraloadMiddleware::class);\n\n        Route::get('/test', fn() => response('ok'));\n        $this->get('/test')->assertStatus(200);\n    }\n\n    protected function tearDown() : void\n    {\n        parent::tearDown();\n        ConditionCallable::$called = false;\n    }\n}\n"
  },
  {
    "path": "tests/Stubs/ConditionCallable.php",
    "content": "<?php\n\nnamespace Tests\\Stubs;\n\nclass ConditionCallable\n{\n    public static bool $called = false;\n\n    public function handle()\n    {\n        static::$called = true;\n\n        return true;\n    }\n}\n"
  }
]