[
  {
    "path": ".docker/etc/php/entrypoint.sh",
    "content": "#!/bin/sh\n\nredis-server --daemonize yes\n\nsetfacl -dR -m u:www-data:rwX /var/www/html\nsetfacl -R -m u:www-data:rwX /var/www/html\n\ndocker-php-entrypoint $@\n"
  },
  {
    "path": ".docker/etc/php/php-v1.ini",
    "content": "memory_limit = 256M\nmax_execution_time = 600\n"
  },
  {
    "path": ".docker/etc/php/php-v2.ini",
    "content": "memory_limit = 256M\nmax_execution_time = 600\nxdebug.mode=coverage\n"
  },
  {
    "path": ".docker/images/php/.bashrc-v1",
    "content": "alias la52='vendor/bin/phpunit --stop-on-failure -c phpunit-laravel-52.xml'\nalias la53='vendor/bin/phpunit --stop-on-failure -c phpunit-laravel-53.xml'\nalias la54='vendor/bin/phpunit --stop-on-failure -c phpunit-laravel-54.xml'\nalias la55='vendor/bin/phpunit --stop-on-failure -c phpunit-laravel-55.xml'\nalias la56='vendor/bin/phpunit --stop-on-failure -c phpunit-laravel-56.xml'\nalias la57='vendor/bin/phpunit --stop-on-failure -c phpunit-laravel-57.xml'\nalias la58='vendor/bin/phpunit --stop-on-failure -c phpunit-laravel-58.xml'\nalias la6='vendor/bin/phpunit --stop-on-failure -c phpunit-laravel-6.xml'\nalias la7='vendor/bin/phpunit --stop-on-failure -c phpunit-laravel-7.xml'\n\nalias phpunit-all='la7 && la6 && la58 && la57 && la56 && la55 && la54 && la53 && la52'\nalias phpunit-c='la7 --coverage-html coverage'\n"
  },
  {
    "path": ".docker/images/php/.bashrc-v2",
    "content": "alias la6='vendor/bin/phpunit --stop-on-failure -c phpunit-laravel-6.xml'\nalias la7='vendor/bin/phpunit --stop-on-failure -c phpunit-laravel-7.xml'\nalias la8='vendor/bin/phpunit --stop-on-failure -c phpunit-laravel-8.xml'\n\nalias la-all='la8 && la7 && la6'\nalias la-c='la8 --coverage-html coverage'\n"
  },
  {
    "path": ".docker/images/php/Dockerfile-v1",
    "content": "FROM php:7.3.10-fpm\n\nCOPY ./.bashrc-v1 /root/.bashrc\n\nRUN apt-get update > /dev/null && apt-get install -y \\\n    acl \\\n    unzip \\\n    libzip-dev \\\n    zlib1g-dev \\\n    libpng-dev \\\n    libjpeg-dev \\\n    nodejs \\\n    redis-server\n\nRUN docker-php-ext-install zip pdo_mysql bcmath gd > /dev/null\n\nRUN pecl install xdebug > /dev/null \\\n    && docker-php-ext-enable xdebug > /dev/null\n\nRUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer > /dev/null\n\nRUN rm -rf /var/lib/apt/lists/*\n"
  },
  {
    "path": ".docker/images/php/Dockerfile-v2",
    "content": "FROM php:8.0.6-fpm\n\nCOPY ./.bashrc-v2 /root/.bashrc\n\nRUN apt-get update > /dev/null && apt-get install -y \\\n    acl \\\n    unzip \\\n    libzip-dev \\\n    zlib1g-dev \\\n    libpng-dev \\\n    libjpeg-dev \\\n    nodejs \\\n    redis-server\n\nRUN docker-php-ext-install zip pdo_mysql bcmath gd > /dev/null\n\nRUN pecl install xdebug > /dev/null \\\n    && docker-php-ext-enable xdebug > /dev/null\n\nRUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer > /dev/null\n\nRUN rm -rf /var/lib/apt/lists/*\n"
  },
  {
    "path": ".gitignore",
    "content": "/client\n/coverage\n/frameworks\n/vendor\n.phpunit.result.cache\ncomposer.lock\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: php\n\nphp:\n    - 7.3.24\n    - 7.4.0\n    - 8.0\n\nservices:\n    - redis-server\n\nbefore_script:\n    - composer install --no-interaction\n\nscript:\n    - vendor/bin/phpunit -c phpunit-laravel-6.xml --coverage-clover build/logs/clover.xml\n    - vendor/bin/phpunit -c phpunit-laravel-7.xml\n    - vendor/bin/phpunit -c phpunit-laravel-8.xml\n\nafter_success:\n    - travis_retry php vendor/bin/php-coveralls  -v\n"
  },
  {
    "path": "LICENSE.md",
    "content": "The MIT License (MIT)\n\nCopyright (c) Janusz Kocik\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated\ndocumentation files (the \"Software\"), to deal in the Software without restriction, including without limitation\nthe rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,\nand to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions\nof the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED\nTO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\nTHE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\nDEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "## Laravel Profiler\n\n[![Build Status](https://travis-ci.org/jkocik/laravel-profiler.svg?branch=master)](https://travis-ci.org/jkocik/laravel-profiler)\n[![Coverage Status](https://coveralls.io/repos/github/jkocik/laravel-profiler/badge.svg?branch=master)](https://coveralls.io/github/jkocik/laravel-profiler?branch=master)\n\nThe aim of this project is to track console and web Laravel framework execution and give developers\nbetter understanding what is going on under the hood. Laravel Profiler is designed for Laravel Framework.\n\n![Laravel Profiler](https://drive.google.com/uc?export=view&id=12TSAEW1butnLfmFxO3Pw4GhF96B8PUSk)\n\n### Supported versions\n\n| Laravel Framework version you have | Laravel Profiler version you should use |\n| ---------------------------------- | --------------------------------------- |\n| 5.2.x - 5.8.x | 1.x |\n| 6.x - 8.x | 2.x |\n\n### How does it work?\n\nProfiler delivers data about Laravel framework execution:\n- when **tests are run** (PHPUnit, Laravel Dusk)\n- when Laravel is executed via **console** (artisan)\n- when Laravel is executed via **browser request**\n- when Laravel is executed via web request not expecting HTML response (**API**)\n- on any other **action that terminates** Laravel framework.\n\nProfiler does not add any routes to your application and does not modify the content of the response.\n\nProfiler is divided into 3 parts:\n- Profiler Package - PHP package for Laravel (this repository)\n- Profiler Client - Single Page Application to review data delivered by Profiler Package\n- Profiler Server - bridge between Profiler Package and Profiler Client.\n\nProfiler Client and Profiler Server both live in [laravel-profiler-client](https://github.com/jkocik/laravel-profiler-client) repository\n\n#### Data flow\n\nProfiler Package tracks Laravel execution and sends collected data to Profiler Server using HTTP.\nProfiler Server passes data to Profiler Client using WebSockets.\n\n#### Trackers\n\nData tracked, collected and delivered to Profiler Client are:\n- auth\n- redis\n- route\n- views\n- events\n- session\n- exceptions\n- server status\n- database queries\n- performance metrics\n- request (web) / input (console)\n- response (web) / output (console)\n- application (Laravel status, config, loaded service providers, container bindings, framework paths)\n\nProfiler and its trackers do their job after request / artisan command is finished.\nThat keeps your framework execution time and peak of memory usage as close to real values (without Profiler impact)\nas possible.\n\n## Installation and configuration\n\n### Step 1: Install Profiler Package\n\nRequirements: PHP 7.2+\n\nIt is recommended to install Profiler Package only for development\n\n```shell\ncomposer require jkocik/laravel-profiler --dev\n```\n\n### Step 2: Publish configuration file\n\nRun command\n\n```shell\nphp artisan vendor:publish --provider=\"JKocik\\Laravel\\Profiler\\ServiceProvider\"\n```\n\n... and check config/profiler.php file for Profiler settings.\n\n### Step 3: Install Profiler Server and Profiler Client\n\nIt is recommended to install Profiler Server and Profiler Client only for development\n\n```shell\nnpm install laravel-profiler-client --save-dev\n```\n\n### Step 4: Run Profiler Server and Profiler Client\n\n_Windows users: If you have any issue with running Profiler Server or Profiler Client\ncheck Installation options / issues section below._\n\nRun command\n\n```shell\nphp artisan profiler:server\n```\nand\n\na) for your local machine\n\n```shell\nphp artisan profiler:client\n```\n\nAfter that your browser should have new tab opened with Profiler Client connected to Profiler Server.\n\nb) for Docker, Vagrant or any other machine different from local\n\n```shell\nphp artisan profiler:client -m\n```\n\n... and open new browser tab according to instructions in console. Remember that you need\nto connect Profiler Client to Profiler Server yourself because by default Profiler Client uses localhost.\nYou can do that in Profiler Client interface.\n\n### Step 5: Verify installation\n\nRun command\n\n```shell\nphp artisan profiler:status\n```\n\n... to check Profiler status and see first data of Laravel execution in Profiler Client.\n\n### Installation options / issues\n\na) If you have any issue with running Profiler Server or Profiler Client use npm scripts instead of artisan commands.\nAdd new scripts to your package.json file\n\n```json\n\"scripts\": {\n    \"profiler-server\": \"node node_modules/laravel-profiler-client/server/server.js http=8099 ws=1901\",\n    \"profiler-client\": \"http-server node_modules/laravel-profiler-client/dist/ -o -s\",\n    \"ps\": \"npm run profiler-server\",\n    \"pc\": \"npm run profiler-client\"    \n}\n```\n\n... then run Profiler Server\n\n```shell\nnpm run ps\n```\n\n... and Profiler Client\n\n```shell\nnpm run pc\n```\n\nb) If you don't want to open new browser tab every time you run Profiler Client command use manual option\n\n```shell\nphp artisan profiler:client -m\n```\n\nc) If default ports used by Profiler are taken on your machine configure them in config/profiler.php file.\n\n### Done!\n \nYou are ready to use Laravel Profiler. Enjoy!\n\n### Usage\n\n#### Performance metrics\n\nProfiler delivers basic performance metrics including peak of memory usage and Laravel execution time.\nYou can extend metrics by using Profiler helper functions:\n\n```php\nprofiler_start('my time metric name');\n\n// my code to track execution time\n\nprofiler_finish('my time metric name');\n``` \n\nThen check results in Profiler Client (Performance > Custom tab). You should keep unique metric names\notherwise duplicates will be skipped and reported as an error (in a way according to your exception handling\nsettings in config/profiler.php file).\n\n_Important notice: remove Profiler helper functions from your code\nbefore moving to production or any environment without Profiler installed._\n\n#### Laravel Profiler for testing environment\n\nWhen testing Profiler will deliver the same data as for regular request / artisan command. However application should be\nterminated. Lets see two default tests Laravel is shipped with:\n\n```php\npublic function testBasicTest()\n{\n    $response = $this->get('/');\n\n    $response->assertStatus(200);\n}\n``` \n\nFirst test will terminate application and Profiler will work as expected. However second test\n\n```php\npublic function testBasicTest()\n{\n    $this->assertTrue(true);\n}\n```\n\n... will not provide any data because this time application is not terminated. You can force\nProfiler to work by adding terminate method:\n\n```php\npublic function testBasicTest()\n{\n    $this->assertTrue(true);\n    \n    $this->app->terminate();\n}\n```\n\nIf you want to reset Profiler trackers you can use Profiler helper:\n```php\npublic function testBasicTest()\n{\n    factory(User::class)->create();\n    \n    profiler_reset();\n    \n    // act and assert\n}\n```\n\n_Important notice related to testing environment: peak of memory usage can not be tracked for each test separately\nso is not shown in Profiler Client._\n\n#### Using together with Laravel Debugbar\n\nIt is not recommended using Laravel Profiler and Laravel Debugbar together. Profiler will finish\nits work after Debugbar and Profiler report of framework execution time and peak of memory usage will\nbe increased by Debugbar activity. Use Profiler or Debugbar one at a time.\n"
  },
  {
    "path": "composer.json",
    "content": "{\n    \"name\": \"jkocik/laravel-profiler\",\n    \"description\": \"Profiler for Laravel Framework\",\n    \"keywords\": [\"laravel\", \"profiler\", \"debugbar\"],\n    \"homepage\": \"https://github.com/jkocik/laravel-profiler\",\n    \"license\": \"MIT\",\n    \"authors\": [\n        {\n            \"name\": \"Janusz Kocik\",\n            \"email\": \"janusz.kocik@gmail.com\"\n        }\n    ],\n    \"require\": {\n        \"php\": \">=7.2\",\n        \"guzzlehttp/guzzle\": \"^5.0 || ^6.0 || ^7.0\"\n    },\n    \"require-dev\": {\n        \"mockery/mockery\": \"^1.0\",\n        \"php-mock/php-mock\": \"^2.0\",\n        \"php-coveralls/php-coveralls\": \"^2.1\",\n        \"predis/predis\": \"^1.1\",\n        \"fzaninotto/faker\": \"^1.5\",\n        \"phpunit/phpunit\": \"^8\"\n    },\n    \"autoload\": {\n        \"psr-4\": {\n            \"JKocik\\\\Laravel\\\\Profiler\\\\\": \"src/\"\n        },\n        \"files\": [\n            \"src/Services/helpers.php\"\n        ]\n    },\n    \"autoload-dev\": {\n        \"psr-4\": {\n            \"JKocik\\\\Laravel\\\\Profiler\\\\Tests\\\\\": \"tests/\"\n        }\n    },\n    \"extra\": {\n        \"laravel\": {\n            \"providers\": [\n                \"JKocik\\\\Laravel\\\\Profiler\\\\ServiceProvider\"\n            ]\n        }\n    }\n}\n"
  },
  {
    "path": "config/profiler.php",
    "content": "<?php\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | General Laravel Profiler enable / disable setting\n    |--------------------------------------------------------------------------\n    |\n    | This value enables / disables Profiler. If set to false all settings\n    | below it do not take effect.\n    |\n    */\n\n    'enabled' => env('PROFILER_ENABLED', true),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Override general Laravel Profiler enable / disable setting\n    |--------------------------------------------------------------------------\n    |\n    | Can disable Profiler on particular env. Profiler is disabled by default\n    | on production (be aware that installation on production is not recommended).\n    | Setting takes effect only if above (enabled) is set to true.\n    |\n    */\n\n    'enabled_overrides' => [\n        'production' => false,\n//        'testing' => false,\n//        'local' => false,\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Profiler trackers\n    |--------------------------------------------------------------------------\n    |\n    | Trackers collect data of framework execution. You can decide what data\n    | you want to collect by commenting / uncommenting particular trackers.\n    |\n    */\n\n    'trackers' => [\n        \\JKocik\\Laravel\\Profiler\\Trackers\\ConfigTracker::class, // App > Config tab\n        \\JKocik\\Laravel\\Profiler\\Trackers\\ServiceProvidersTracker::class, // App > Service Providers tab\n        \\JKocik\\Laravel\\Profiler\\Trackers\\BindingsTracker::class, // App > Bindings tab\n        \\JKocik\\Laravel\\Profiler\\Trackers\\PathsTracker::class, // App > Paths tab\n        \\JKocik\\Laravel\\Profiler\\Trackers\\SessionTracker::class, // Request > Session tab\n        \\JKocik\\Laravel\\Profiler\\Trackers\\RouteTracker::class, // Request > Route tab\n        \\JKocik\\Laravel\\Profiler\\Trackers\\ServerTracker::class, // Request > Server tab\n        \\JKocik\\Laravel\\Profiler\\Trackers\\ContentTracker::class, // Response > Content and JSON tabs\n        \\JKocik\\Laravel\\Profiler\\Trackers\\ViewsTracker::class, // Views tab\n        \\JKocik\\Laravel\\Profiler\\Trackers\\EventsTracker::class, // Events tab\n        \\JKocik\\Laravel\\Profiler\\Trackers\\QueriesTracker::class, // Queries tab\n//        \\JKocik\\Laravel\\Profiler\\Trackers\\RedisTracker::class, // Redis tab (from Laravel 5.7)\n        \\JKocik\\Laravel\\Profiler\\Trackers\\AuthTracker::class, // Auth tab\n        \\JKocik\\Laravel\\Profiler\\Trackers\\ExceptionTracker::class, // Exception tab\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Profiler Server and Profiler Client connections\n    |--------------------------------------------------------------------------\n    |\n    | These settings let you set up connections between Profiler Package\n    | (this Laravel package) and Profiler Server using HTTP protocol\n    | and finally pass data from Profiler Server to Profiler Client\n    | (Single Page Application accessible via browser) using WebSockets.\n    |\n    */\n\n    'server_http' => [\n        'address' => 'http://localhost',\n        'port' => '8099',\n    ],\n\n    'server_sockets' => [\n        'port' => '1901',\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Profiler processors\n    |--------------------------------------------------------------------------\n    |\n    | Processors process data collected by trackers. Default processor\n    | broadcasts data through Profiler Server to Profiler Client.\n    |\n    */\n\n    'processors' => [\n        \\JKocik\\Laravel\\Profiler\\Processors\\BroadcastingProcessor::class,\n    ],\n\n    'turn_off_processors_for_paths' => [\n        'telescope',\n        '_debugbar',\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Data passed to tracked items\n    |--------------------------------------------------------------------------\n    |\n    | That can be very heavy when your views or events receive a lot of data.\n    | Avoid using it on testing env specially when running whole test suite.\n    |\n    */\n\n    'data' => [\n        'views' => false,\n        'events' => false,\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Grouping\n    |--------------------------------------------------------------------------\n    |\n    | There can be a lot of the same events fired one by one. Grouping can\n    | help you review them on better organized list of events.\n    |\n    */\n\n    'group' => [\n        'events' => true,\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Handle exceptions\n    |--------------------------------------------------------------------------\n    |\n    | Profiler processors and helper functions can throw exceptions.\n    | They are logged by default to let you know about current issues\n    | like problems with connection to Profiler Server.\n    |\n    | Handle exceptions settings are [int]:\n    | 0 - catch exceptions and do not report them\n    | 1 - catch exceptions and report them in logs\n    | 666 - do not catch exceptions, let them be thrown\n    |\n    */\n\n    'handle_exceptions' => 1,\n\n];\n"
  },
  {
    "path": "docker-compose.yml",
    "content": "version: '3.5'\n\nservices:\n    profiler_v1:\n        build:\n            dockerfile: Dockerfile-v1\n            context: ./.docker/images/php\n        container_name: profiler_v1\n        hostname: profiler_v1\n        entrypoint: sh /bin/entrypoint.sh php-fpm\n        volumes:\n            - ./.docker/etc/php/entrypoint.sh:/bin/entrypoint.sh:ro\n            - ./.docker/etc/php/php-v1.ini:/usr/local/etc/php/php.ini\n            - .:/var/www/html\n\n    profiler_v2:\n        build:\n            dockerfile: Dockerfile-v2\n            context: ./.docker/images/php\n        container_name: profiler_v2\n        hostname: profiler_v2\n        entrypoint: sh /bin/entrypoint.sh php-fpm\n        volumes:\n            - ./.docker/etc/php/entrypoint.sh:/bin/entrypoint.sh:ro\n            - ./.docker/etc/php/php-v2.ini:/usr/local/etc/php/php.ini\n            - .:/var/www/html\n"
  },
  {
    "path": "phpunit-laravel-52.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<phpunit bootstrap=\"./tests/bootstrap/phpunit.php\"\n          colors=\"true\"\n          convertErrorsToExceptions=\"true\"\n          convertNoticesToExceptions=\"true\"\n          convertWarningsToExceptions=\"true\"\n          stopOnFailure=\"false\"\n>\n    <testsuites>\n        <testsuite name=\"Feature\">\n            <directory suffix=\"Test.php\">./tests/Feature</directory>\n        </testsuite>\n        <testsuite name=\"Unit\">\n            <directory suffix=\"Test.php\">./tests/Unit</directory>\n        </testsuite>\n    </testsuites>\n    <filter>\n        <whitelist processUncoveredFilesFromWhitelist=\"true\">\n            <directory suffix=\".php\">./src/</directory>\n        </whitelist>\n    </filter>\n    <listeners>\n        <listener class=\"\\JKocik\\Laravel\\Profiler\\Tests\\Support\\TestListener\">\n        </listener>\n    </listeners>\n    <php>\n        <const name=\"TESTS_FRAMEWORK_VERSION\" value=\"5.2\"/>\n        <env name=\"DB_CONNECTION\" value=\"sqlite\"/>\n        <env name=\"DB_DATABASE\" value=\":memory:\"/>\n    </php>\n</phpunit>\n"
  },
  {
    "path": "phpunit-laravel-53.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<phpunit bootstrap=\"./tests/bootstrap/phpunit.php\"\n          colors=\"true\"\n          convertErrorsToExceptions=\"true\"\n          convertNoticesToExceptions=\"true\"\n          convertWarningsToExceptions=\"true\"\n          stopOnFailure=\"false\"\n>\n    <testsuites>\n        <testsuite name=\"Feature\">\n            <directory suffix=\"Test.php\">./tests/Feature</directory>\n        </testsuite>\n        <testsuite name=\"Unit\">\n            <directory suffix=\"Test.php\">./tests/Unit</directory>\n        </testsuite>\n    </testsuites>\n    <filter>\n        <whitelist processUncoveredFilesFromWhitelist=\"true\">\n            <directory suffix=\".php\">./src/</directory>\n        </whitelist>\n    </filter>\n    <listeners>\n        <listener class=\"\\JKocik\\Laravel\\Profiler\\Tests\\Support\\TestListener\">\n        </listener>\n    </listeners>\n    <php>\n        <const name=\"TESTS_FRAMEWORK_VERSION\" value=\"5.3\"/>\n        <env name=\"DB_CONNECTION\" value=\"sqlite\"/>\n        <env name=\"DB_DATABASE\" value=\":memory:\"/>\n    </php>\n</phpunit>\n"
  },
  {
    "path": "phpunit-laravel-54.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<phpunit bootstrap=\"./tests/bootstrap/phpunit.php\"\n          colors=\"true\"\n          convertErrorsToExceptions=\"true\"\n          convertNoticesToExceptions=\"true\"\n          convertWarningsToExceptions=\"true\"\n          stopOnFailure=\"false\"\n>\n    <testsuites>\n        <testsuite name=\"Feature\">\n            <directory suffix=\"Test.php\">./tests/Feature</directory>\n        </testsuite>\n        <testsuite name=\"Unit\">\n            <directory suffix=\"Test.php\">./tests/Unit</directory>\n        </testsuite>\n    </testsuites>\n    <filter>\n        <whitelist processUncoveredFilesFromWhitelist=\"true\">\n            <directory suffix=\".php\">./src/</directory>\n        </whitelist>\n    </filter>\n    <listeners>\n        <listener class=\"\\JKocik\\Laravel\\Profiler\\Tests\\Support\\TestListener\">\n        </listener>\n    </listeners>\n    <php>\n        <const name=\"TESTS_FRAMEWORK_VERSION\" value=\"5.4\"/>\n        <env name=\"DB_CONNECTION\" value=\"sqlite\"/>\n        <env name=\"DB_DATABASE\" value=\":memory:\"/>\n    </php>\n</phpunit>\n"
  },
  {
    "path": "phpunit-laravel-55.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<phpunit bootstrap=\"./tests/bootstrap/phpunit.php\"\n          colors=\"true\"\n          convertErrorsToExceptions=\"true\"\n          convertNoticesToExceptions=\"true\"\n          convertWarningsToExceptions=\"true\"\n          stopOnFailure=\"false\"\n>\n    <testsuites>\n        <testsuite name=\"Feature\">\n            <directory suffix=\"Test.php\">./tests/Feature</directory>\n        </testsuite>\n        <testsuite name=\"Unit\">\n            <directory suffix=\"Test.php\">./tests/Unit</directory>\n        </testsuite>\n    </testsuites>\n    <filter>\n        <whitelist processUncoveredFilesFromWhitelist=\"true\">\n            <directory suffix=\".php\">./src/</directory>\n        </whitelist>\n    </filter>\n    <listeners>\n        <listener class=\"\\JKocik\\Laravel\\Profiler\\Tests\\Support\\TestListener\">\n        </listener>\n    </listeners>\n    <php>\n        <const name=\"TESTS_FRAMEWORK_VERSION\" value=\"5.5\"/>\n        <env name=\"DB_CONNECTION\" value=\"sqlite\"/>\n        <env name=\"DB_DATABASE\" value=\":memory:\"/>\n    </php>\n</phpunit>\n"
  },
  {
    "path": "phpunit-laravel-56.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<phpunit bootstrap=\"./tests/bootstrap/phpunit.php\"\n          colors=\"true\"\n          convertErrorsToExceptions=\"true\"\n          convertNoticesToExceptions=\"true\"\n          convertWarningsToExceptions=\"true\"\n          stopOnFailure=\"false\"\n>\n    <testsuites>\n        <testsuite name=\"Feature\">\n            <directory suffix=\"Test.php\">./tests/Feature</directory>\n        </testsuite>\n        <testsuite name=\"Unit\">\n            <directory suffix=\"Test.php\">./tests/Unit</directory>\n        </testsuite>\n    </testsuites>\n    <filter>\n        <whitelist processUncoveredFilesFromWhitelist=\"true\">\n            <directory suffix=\".php\">./src/</directory>\n        </whitelist>\n    </filter>\n    <listeners>\n        <listener class=\"\\JKocik\\Laravel\\Profiler\\Tests\\Support\\TestListener\">\n        </listener>\n    </listeners>\n    <php>\n        <const name=\"TESTS_FRAMEWORK_VERSION\" value=\"5.6\"/>\n        <env name=\"DB_CONNECTION\" value=\"sqlite\"/>\n        <env name=\"DB_DATABASE\" value=\":memory:\"/>\n    </php>\n</phpunit>\n"
  },
  {
    "path": "phpunit-laravel-57.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<phpunit bootstrap=\"./tests/bootstrap/phpunit.php\"\n          colors=\"true\"\n          convertErrorsToExceptions=\"true\"\n          convertNoticesToExceptions=\"true\"\n          convertWarningsToExceptions=\"true\"\n          stopOnFailure=\"false\"\n>\n    <testsuites>\n        <testsuite name=\"Feature\">\n            <directory suffix=\"Test.php\">./tests/Feature</directory>\n        </testsuite>\n        <testsuite name=\"Unit\">\n            <directory suffix=\"Test.php\">./tests/Unit</directory>\n        </testsuite>\n    </testsuites>\n    <filter>\n        <whitelist processUncoveredFilesFromWhitelist=\"true\">\n            <directory suffix=\".php\">./src/</directory>\n        </whitelist>\n    </filter>\n    <listeners>\n        <listener class=\"\\JKocik\\Laravel\\Profiler\\Tests\\Support\\TestListener\">\n        </listener>\n    </listeners>\n    <php>\n        <const name=\"TESTS_FRAMEWORK_VERSION\" value=\"5.7\"/>\n        <env name=\"DB_CONNECTION\" value=\"sqlite\"/>\n        <env name=\"DB_DATABASE\" value=\":memory:\"/>\n    </php>\n</phpunit>\n"
  },
  {
    "path": "phpunit-laravel-58.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<phpunit bootstrap=\"./tests/bootstrap/phpunit.php\"\n          colors=\"true\"\n          convertErrorsToExceptions=\"true\"\n          convertNoticesToExceptions=\"true\"\n          convertWarningsToExceptions=\"true\"\n          stopOnFailure=\"false\"\n>\n    <testsuites>\n        <testsuite name=\"Feature\">\n            <directory suffix=\"Test.php\">./tests/Feature</directory>\n        </testsuite>\n        <testsuite name=\"Unit\">\n            <directory suffix=\"Test.php\">./tests/Unit</directory>\n        </testsuite>\n    </testsuites>\n    <filter>\n        <whitelist processUncoveredFilesFromWhitelist=\"true\">\n            <directory suffix=\".php\">./src/</directory>\n        </whitelist>\n    </filter>\n    <listeners>\n        <listener class=\"\\JKocik\\Laravel\\Profiler\\Tests\\Support\\TestListener\">\n        </listener>\n    </listeners>\n    <php>\n        <const name=\"TESTS_FRAMEWORK_VERSION\" value=\"5.8\"/>\n        <env name=\"DB_CONNECTION\" value=\"sqlite\"/>\n        <env name=\"DB_DATABASE\" value=\":memory:\"/>\n    </php>\n</phpunit>\n"
  },
  {
    "path": "phpunit-laravel-6.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<phpunit bootstrap=\"./tests/bootstrap/phpunit.php\"\n          colors=\"true\"\n          convertErrorsToExceptions=\"true\"\n          convertNoticesToExceptions=\"true\"\n          convertWarningsToExceptions=\"true\"\n          stopOnFailure=\"false\"\n>\n    <testsuites>\n        <testsuite name=\"Feature\">\n            <directory suffix=\"Test.php\">./tests/Feature</directory>\n        </testsuite>\n        <testsuite name=\"Unit\">\n            <directory suffix=\"Test.php\">./tests/Unit</directory>\n        </testsuite>\n    </testsuites>\n    <filter>\n        <whitelist>\n            <directory suffix=\".php\">./src/</directory>\n            <exclude>\n                <file>./src/LaravelExecution/ExceptionHandlerFromVersion7.php</file>\n            </exclude>\n        </whitelist>\n    </filter>\n    <listeners>\n        <listener class=\"\\JKocik\\Laravel\\Profiler\\Tests\\Support\\TestListener\">\n        </listener>\n    </listeners>\n    <php>\n        <const name=\"TESTS_FRAMEWORK_VERSION\" value=\"6\"/>\n        <env name=\"DB_CONNECTION\" value=\"sqlite\"/>\n        <env name=\"DB_DATABASE\" value=\":memory:\"/>\n        <env name=\"REDIS_CLIENT\" value=\"predis\"/>\n    </php>\n</phpunit>\n"
  },
  {
    "path": "phpunit-laravel-7.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<phpunit bootstrap=\"./tests/bootstrap/phpunit.php\"\n          colors=\"true\"\n          convertErrorsToExceptions=\"true\"\n          convertNoticesToExceptions=\"true\"\n          convertWarningsToExceptions=\"true\"\n          stopOnFailure=\"false\"\n>\n    <testsuites>\n        <testsuite name=\"Feature\">\n            <directory suffix=\"Test.php\">./tests/Feature</directory>\n        </testsuite>\n        <testsuite name=\"Unit\">\n            <directory suffix=\"Test.php\">./tests/Unit</directory>\n        </testsuite>\n    </testsuites>\n    <filter>\n        <whitelist processUncoveredFilesFromWhitelist=\"true\">\n            <directory suffix=\".php\">./src/</directory>\n        </whitelist>\n    </filter>\n    <listeners>\n        <listener class=\"\\JKocik\\Laravel\\Profiler\\Tests\\Support\\TestListener\">\n        </listener>\n    </listeners>\n    <php>\n        <const name=\"TESTS_FRAMEWORK_VERSION\" value=\"7\"/>\n        <env name=\"DB_CONNECTION\" value=\"sqlite\"/>\n        <env name=\"DB_DATABASE\" value=\":memory:\"/>\n        <env name=\"REDIS_CLIENT\" value=\"predis\"/>\n    </php>\n</phpunit>\n"
  },
  {
    "path": "phpunit-laravel-8.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<phpunit bootstrap=\"./tests/bootstrap/phpunit.php\"\n          colors=\"true\"\n          convertErrorsToExceptions=\"true\"\n          convertNoticesToExceptions=\"true\"\n          convertWarningsToExceptions=\"true\"\n          stopOnFailure=\"false\"\n>\n    <testsuites>\n        <testsuite name=\"Feature\">\n            <directory suffix=\"Test.php\">./tests/Feature</directory>\n        </testsuite>\n        <testsuite name=\"Unit\">\n            <directory suffix=\"Test.php\">./tests/Unit</directory>\n        </testsuite>\n    </testsuites>\n    <filter>\n        <whitelist processUncoveredFilesFromWhitelist=\"true\">\n            <directory suffix=\".php\">./src/</directory>\n        </whitelist>\n    </filter>\n    <listeners>\n        <listener class=\"\\JKocik\\Laravel\\Profiler\\Tests\\Support\\TestListener\">\n        </listener>\n    </listeners>\n    <php>\n        <const name=\"TESTS_FRAMEWORK_VERSION\" value=\"8\"/>\n        <env name=\"DB_CONNECTION\" value=\"sqlite\"/>\n        <env name=\"DB_DATABASE\" value=\":memory:\"/>\n        <env name=\"REDIS_CLIENT\" value=\"predis\"/>\n    </php>\n</phpunit>\n"
  },
  {
    "path": "src/BaseProfiler.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler;\n\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Foundation\\Application;\nuse Illuminate\\Console\\Events\\ArtisanStarting;\nuse JKocik\\Laravel\\Profiler\\Contracts\\Profiler;\nuse JKocik\\Laravel\\Profiler\\Events\\ResetTrackers;\nuse Illuminate\\Foundation\\Bootstrap\\BootProviders;\nuse JKocik\\Laravel\\Profiler\\Console\\StatusCommand;\nuse JKocik\\Laravel\\Profiler\\Console\\ServerCommand;\nuse JKocik\\Laravel\\Profiler\\Console\\ClientCommand;\n\nabstract class BaseProfiler implements Profiler\n{\n    /**\n     * @var Application\n     */\n    protected $app;\n\n    /**\n     * BaseProfiler constructor.\n     * @param Application $app\n     */\n    public function __construct(Application $app)\n    {\n        $this->app = $app;\n    }\n\n    /**\n     * @return void\n     */\n    public function resetTrackers(): void\n    {\n        event(new ResetTrackers());\n    }\n\n    /**\n     * @return void\n     */\n    public function listenForBoot(): void\n    {\n        $this->app->beforeBootstrapping(BootProviders::class, function () {\n            $this->commands();\n            $this->boot();\n        });\n    }\n\n    /**\n     * @return void\n     */\n    abstract protected function boot(): void;\n\n    /**\n     * @return void\n     */\n    private function commands(): void\n    {\n        Event::listen(ArtisanStarting::class, function (ArtisanStarting $event) {\n            $event->artisan->resolveCommands([\n                StatusCommand::class,\n                ServerCommand::class,\n                ClientCommand::class,\n            ]);\n        });\n    }\n}\n"
  },
  {
    "path": "src/Console/ClientCommand.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Console;\n\nuse Illuminate\\Console\\Command;\nuse JKocik\\Laravel\\Profiler\\Services\\ConsoleService;\n\nclass ClientCommand extends Command\n{\n    /**\n     * @var string\n     */\n    protected $signature = 'profiler:client {--m|manual}';\n\n    /**\n     * @var string\n     */\n    protected $description = 'Start Profiler Client';\n\n    /**\n     * @var ConsoleService\n     */\n    protected $consoleService;\n\n    /**\n     * ClientCommand constructor.\n     * @param ConsoleService $consoleService\n     */\n    public function __construct(ConsoleService $consoleService)\n    {\n        parent::__construct();\n\n        $this->consoleService = $consoleService;\n    }\n\n    /**\n     * @return void\n     */\n    public function handle(): void\n    {\n        $this->line('Starting Profiler Client ...');\n\n        passthru($this->consoleService->profilerClientCmd($this->option('manual')));\n    }\n}\n"
  },
  {
    "path": "src/Console/ServerCommand.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Console;\n\nuse Illuminate\\Console\\Command;\nuse JKocik\\Laravel\\Profiler\\Services\\ConsoleService;\n\nclass ServerCommand extends Command\n{\n    /**\n     * @var string\n     */\n    protected $signature = 'profiler:server';\n\n    /**\n     * @var string\n     */\n    protected $description = 'Start Profiler Server';\n\n    /**\n     * @var ConsoleService\n     */\n    protected $consoleService;\n\n    /**\n     * ServerCommand constructor.\n     * @param ConsoleService $consoleService\n     */\n    public function __construct(ConsoleService $consoleService)\n    {\n        parent::__construct();\n\n        $this->consoleService = $consoleService;\n    }\n\n    /**\n     * @return void\n     */\n    public function handle(): void\n    {\n        $this->line('Starting Profiler Server ...');\n\n        passthru($this->consoleService->profilerServerCmd());\n    }\n}\n"
  },
  {
    "path": "src/Console/StatusCommand.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Console;\n\nuse Illuminate\\Console\\Command;\nuse Illuminate\\Support\\Facades\\Event;\nuse JKocik\\Laravel\\Profiler\\Services\\ConfigService;\nuse JKocik\\Laravel\\Profiler\\Services\\ConsoleService;\nuse JKocik\\Laravel\\Profiler\\Processors\\StatusCommandProcessor;\nuse JKocik\\Laravel\\Profiler\\Events\\ProfilerServerConnectionFailed;\nuse JKocik\\Laravel\\Profiler\\Events\\ProfilerServerConnectionSuccessful;\n\nclass StatusCommand extends Command\n{\n    /**\n     * @var string\n     */\n    protected $signature = 'profiler:status';\n\n    /**\n     * @var string\n     */\n    protected $description = 'Check Laravel Profiler status';\n\n    /**\n     * @var ConfigService\n     */\n    protected $configService;\n\n    /**\n     * @var ConsoleService\n     */\n    protected $consoleService;\n\n    /**\n     * @var bool\n     */\n    protected $connectionStatusIsUnknown = true;\n\n    /**\n     * StatusCommand constructor.\n     * @param ConfigService $configService\n     * @param ConsoleService $consoleService\n     */\n    public function __construct(ConfigService $configService, ConsoleService $consoleService)\n    {\n        parent::__construct();\n\n        $this->configService = $configService;\n        $this->consoleService = $consoleService;\n    }\n\n    /**\n     * @return void\n     */\n    public function handle(): void\n    {\n        $this->configService->overrideProcessors([\n            StatusCommandProcessor::class,\n        ]);\n\n        $this->printProfilerStatus();\n\n        if (! $this->configService->isProfilerEnabled()) {\n            return;\n        }\n\n        $this->printTrackersStatus();\n\n        $this->printConnectionStatus();\n    }\n\n    /**\n     * @return void\n     */\n    protected function printProfilerStatus(): void\n    {\n        $this->line(\"1) {$this->consoleService->envInfo()}\");\n        $this->info($this->consoleService->profilerStatusInfo());\n    }\n\n    /**\n     * @return void\n     */\n    protected function printTrackersStatus(): void\n    {\n        $this->line('');\n        $this->line(\"2) {$this->consoleService->trackersStatusInfo()}\");\n\n        $this->configService->trackers()->each(function ($tracker) {\n            $this->info(\"- {$tracker}\");\n        });\n\n        $this->comment($this->consoleService->trackersCommentLine1());\n        $this->comment($this->consoleService->trackersCommentLine2());\n    }\n\n    /**\n     * @return void\n     */\n    protected function printConnectionStatus(): void\n    {\n        $this->line('');\n        $this->line(\"3) {$this->consoleService->connectionStatusInfo()}\");\n\n        Event::listen(ProfilerServerConnectionSuccessful::class, function (ProfilerServerConnectionSuccessful $event) {\n            $this->info($this->consoleService->connectionSuccessfulInfo());\n            $this->info($this->consoleService->connectionSuccessfulSocketsInfo($event->socketsPort));\n            $this->info($this->consoleService->connectionSuccessfulClientsInfo($event->countClients));\n\n            $this->connectionStatusIsUnknown = false;\n        });\n\n        Event::listen(ProfilerServerConnectionFailed::class, function () {\n            $this->error($this->error($this->consoleService->connectionFailedInfo()));\n\n            $this->connectionStatusIsUnknown = false;\n        });\n\n        app()->terminating(function () {\n            if (! $this->connectionStatusIsUnknown) {\n                return;\n            }\n\n            $this->error($this->consoleService->connectionStatusUnknownInfo());\n        });\n    }\n}\n"
  },
  {
    "path": "src/Contracts/DataProcessor.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Contracts;\n\ninterface DataProcessor\n{\n    /**\n     * @param DataTracker $dataTracker\n     * @return void\n     */\n    public function process(DataTracker $dataTracker): void;\n}\n"
  },
  {
    "path": "src/Contracts/DataTracker.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Contracts;\n\nuse Illuminate\\Support\\Collection;\n\ninterface DataTracker\n{\n    /**\n     * @return void\n     */\n    public function track(): void;\n\n    /**\n     * @return void\n     */\n    public function terminate(): void;\n\n    /**\n     * @return Collection\n     */\n    public function meta(): Collection;\n\n    /**\n     * @return Collection\n     */\n    public function data(): Collection;\n}\n"
  },
  {
    "path": "src/Contracts/ExecutionContent.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Contracts;\n\nuse Illuminate\\Support\\Collection;\n\ninterface ExecutionContent\n{\n    /**\n     * @return Collection\n     */\n    public function meta(): Collection;\n\n    /**\n     * @return Collection\n     */\n    public function data(): Collection;\n}\n"
  },
  {
    "path": "src/Contracts/ExecutionData.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Contracts;\n\ninterface ExecutionData\n{\n    /**\n     * @param ExecutionRequest $request\n     * @return void\n     */\n    public function setRequest(ExecutionRequest $request): void;\n\n    /**\n     * @return ExecutionRequest\n     */\n    public function request(): ExecutionRequest;\n\n    /**\n     * @param ExecutionRoute $route\n     * @return void\n     */\n    public function setRoute(ExecutionRoute $route): void;\n\n    /**\n     * @return ExecutionRoute\n     */\n    public function route(): ExecutionRoute;\n\n    /**\n     * @param ExecutionSession $session\n     * @return void\n     */\n    public function setSession(ExecutionSession $session): void;\n\n    /**\n     * @return ExecutionSession\n     */\n    public function session(): ExecutionSession;\n\n    /**\n     * @param ExecutionServer $server\n     * @return void\n     */\n    public function setServer(ExecutionServer $server): void;\n\n    /**\n     * @return ExecutionServer\n     */\n    public function server(): ExecutionServer;\n\n    /**\n     * @param ExecutionResponse $response\n     * @return void\n     */\n    public function setResponse(ExecutionResponse $response): void;\n\n    /**\n     * @return ExecutionResponse\n     */\n    public function response(): ExecutionResponse;\n\n    /**\n     * @param ExecutionContent $content\n     * @return void\n     */\n    public function setContent(ExecutionContent $content): void;\n\n    /**\n     * @return ExecutionContent\n     */\n    public function content(): ExecutionContent;\n}\n"
  },
  {
    "path": "src/Contracts/ExecutionRequest.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Contracts;\n\nuse Illuminate\\Support\\Collection;\n\ninterface ExecutionRequest\n{\n    /**\n     * @return Collection\n     */\n    public function meta(): Collection;\n\n    /**\n     * @return Collection\n     */\n    public function data(): Collection;\n}\n"
  },
  {
    "path": "src/Contracts/ExecutionResponse.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Contracts;\n\nuse Illuminate\\Support\\Collection;\n\ninterface ExecutionResponse\n{\n    /**\n     * @return Collection\n     */\n    public function meta(): Collection;\n\n    /**\n     * @return Collection\n     */\n    public function data(): Collection;\n}\n"
  },
  {
    "path": "src/Contracts/ExecutionRoute.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Contracts;\n\nuse Illuminate\\Support\\Collection;\n\ninterface ExecutionRoute\n{\n    /**\n     * @return Collection\n     */\n    public function meta(): Collection;\n\n    /**\n     * @return Collection\n     */\n    public function data(): Collection;\n}\n"
  },
  {
    "path": "src/Contracts/ExecutionServer.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Contracts;\n\nuse Illuminate\\Support\\Collection;\n\ninterface ExecutionServer\n{\n    /**\n     * @return Collection\n     */\n    public function meta(): Collection;\n\n    /**\n     * @return Collection\n     */\n    public function data(): Collection;\n}\n"
  },
  {
    "path": "src/Contracts/ExecutionSession.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Contracts;\n\nuse Illuminate\\Support\\Collection;\n\ninterface ExecutionSession\n{\n    /**\n     * @return Collection\n     */\n    public function meta(): Collection;\n\n    /**\n     * @return Collection\n     */\n    public function data(): Collection;\n}\n"
  },
  {
    "path": "src/Contracts/ExecutionWatcher.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Contracts;\n\ninterface ExecutionWatcher\n{\n    /**\n     * @return void\n     */\n    public function watch(): void;\n}\n"
  },
  {
    "path": "src/Contracts/LaravelListener.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Contracts;\n\ninterface LaravelListener\n{\n    /**\n     * @return void\n     */\n    public function listen(): void;\n}\n"
  },
  {
    "path": "src/Contracts/Memory.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Contracts;\n\ninterface Memory\n{\n\n}\n"
  },
  {
    "path": "src/Contracts/Processor.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Contracts;\n\ninterface Processor\n{\n    /**\n     * @param DataTracker $dataTracker\n     * @return void\n     */\n    public function process(DataTracker $dataTracker): void;\n}\n"
  },
  {
    "path": "src/Contracts/Profiler.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Contracts;\n\ninterface Profiler\n{\n    /**\n     * @return void\n     */\n    public function resetTrackers(): void;\n\n    /**\n     * @return void\n     */\n    public function listenForBoot(): void;\n}\n"
  },
  {
    "path": "src/Contracts/Timer.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Contracts;\n\ninterface Timer\n{\n    /**\n     * @param string $name\n     * @return void\n     */\n    public function startCustom(string $name): void;\n\n    /**\n     * @param string $name\n     * @return void\n     */\n    public function finishCustom(string $name): void;\n\n    /**\n     * @param string $name\n     * @return float\n     */\n    public function millisecondsCustom(string $name): float;\n}\n"
  },
  {
    "path": "src/Contracts/Tracker.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Contracts;\n\nuse Illuminate\\Support\\Collection;\n\ninterface Tracker\n{\n    /**\n     * @return Collection\n     */\n    public function meta(): Collection;\n\n    /**\n     * @return Collection\n     */\n    public function data(): Collection;\n\n    /**\n     * @return void\n     */\n    public function terminate(): void;\n}\n"
  },
  {
    "path": "src/DisabledProfiler.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler;\n\nuse JKocik\\Laravel\\Profiler\\Contracts\\Timer;\nuse JKocik\\Laravel\\Profiler\\Events\\ProfilerBound;\nuse JKocik\\Laravel\\Profiler\\Services\\Performance\\NullTimerService;\n\nclass DisabledProfiler extends BaseProfiler\n{\n    /**\n     * @return void\n     */\n    protected function boot(): void\n    {\n        $this->bind();\n    }\n\n    /**\n     * @return void\n     */\n    protected function bind(): void\n    {\n        $this->app->singleton(Timer::class, function ($app) {\n            return $app->make(NullTimerService::class);\n        });\n\n        event(ProfilerBound::class);\n    }\n}\n"
  },
  {
    "path": "src/Events/ExceptionHandling.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Events;\n\nuse Throwable;\n\nclass ExceptionHandling\n{\n    /**\n     * @var Throwable\n     */\n    public $exception;\n\n    /**\n     * ExceptionHandling constructor.\n     * @param Throwable $exception\n     */\n    public function __construct(Throwable $exception)\n    {\n        $this->exception = $exception;\n    }\n}\n"
  },
  {
    "path": "src/Events/ProfilerBound.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Events;\n\nclass ProfilerBound\n{\n\n}\n"
  },
  {
    "path": "src/Events/ProfilerServerConnectionFailed.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Events;\n\nclass ProfilerServerConnectionFailed\n{\n\n}\n"
  },
  {
    "path": "src/Events/ProfilerServerConnectionSuccessful.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Events;\n\nclass ProfilerServerConnectionSuccessful\n{\n    /**\n     * @var int\n     */\n    public $socketsPort;\n\n    /**\n     * @var int\n     */\n    public $countClients;\n\n    /**\n     * ProfilerServerConnectionSuccessful constructor.\n     * @param int $socketsPort\n     * @param int $countClients\n     */\n    public function __construct(int $socketsPort, int $countClients)\n    {\n        $this->socketsPort = $socketsPort;\n        $this->countClients = $countClients;\n    }\n}\n"
  },
  {
    "path": "src/Events/ResetTrackers.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Events;\n\nclass ResetTrackers\n{\n\n}\n"
  },
  {
    "path": "src/Events/Terminating.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Events;\n\nclass Terminating\n{\n\n}\n"
  },
  {
    "path": "src/Events/Tracking.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Events;\n\nclass Tracking\n{\n\n}\n"
  },
  {
    "path": "src/LaravelDataProcessor.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler;\n\nuse Exception;\nuse Illuminate\\Foundation\\Application;\nuse JKocik\\Laravel\\Profiler\\Services\\LogService;\nuse JKocik\\Laravel\\Profiler\\Contracts\\Processor;\nuse JKocik\\Laravel\\Profiler\\Contracts\\DataTracker;\nuse JKocik\\Laravel\\Profiler\\Services\\ConfigService;\nuse JKocik\\Laravel\\Profiler\\Contracts\\DataProcessor;\n\nclass LaravelDataProcessor implements DataProcessor\n{\n    /**\n     * @var Application\n     */\n    protected $app;\n\n    /**\n     * @var LogService\n     */\n    protected $logService;\n\n    /**\n     * @var ConfigService\n     */\n    protected $configService;\n\n    /**\n     * LaravelDataProcessor constructor.\n     * @param Application $app\n     * @param LogService $logService\n     * @param ConfigService $configService\n     */\n    public function __construct(\n        Application $app,\n        LogService $logService,\n        ConfigService $configService\n    ) {\n        $this->app = $app;\n        $this->logService = $logService;\n        $this->configService = $configService;\n    }\n\n    /**\n     * @param DataTracker $dataTracker\n     * @return void\n     */\n    public function process(DataTracker $dataTracker): void\n    {\n        if ($this->shouldNotProcess($dataTracker)) {\n            return;\n        }\n\n        $this->configService->processors()->each(function (string $processor) use ($dataTracker) {\n            try {\n                $this->make($processor)->process($dataTracker);\n            } catch (Exception $e) {\n                $this->logService->error($e);\n            }\n        });\n    }\n\n    /**\n     * @param string $processor\n     * @return Processor\n     */\n    protected function make(string $processor): Processor\n    {\n        return $this->app->make($processor);\n    }\n\n    /**\n     * @param DataTracker $dataTracker\n     * @return bool\n     */\n    protected function shouldNotProcess(DataTracker $dataTracker): bool\n    {\n        if (! $dataTracker->meta()->has('path')) {\n            return false;\n        }\n\n        return $this->configService->pathsToTurnOffProcessors()->map(function ($path) use ($dataTracker) {\n            return stripos($dataTracker->meta()->get('path'), $path) !== false;\n        })->contains(true);\n    }\n}\n"
  },
  {
    "path": "src/LaravelDataTracker.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler;\n\nuse Illuminate\\Support\\Collection;\nuse Illuminate\\Foundation\\Application;\nuse JKocik\\Laravel\\Profiler\\Contracts\\Tracker;\nuse JKocik\\Laravel\\Profiler\\Contracts\\DataTracker;\nuse JKocik\\Laravel\\Profiler\\Services\\ConfigService;\nuse JKocik\\Laravel\\Profiler\\Trackers\\RequestTracker;\nuse JKocik\\Laravel\\Profiler\\Trackers\\ResponseTracker;\nuse JKocik\\Laravel\\Profiler\\Trackers\\ApplicationTracker;\nuse JKocik\\Laravel\\Profiler\\Trackers\\PerformanceTracker;\n\nclass LaravelDataTracker implements DataTracker\n{\n    /**\n     * @var Application\n     */\n    protected $app;\n\n    /**\n     * @var ConfigService\n     */\n    protected $configService;\n\n    /**\n     * @var Collection\n     */\n    protected $trackers;\n\n    /**\n     * @var Collection\n     */\n    protected $meta;\n\n    /**\n     * @var Collection\n     */\n    protected $data;\n\n    /**\n     * LaravelDataTracker constructor.\n     * @param Application $app\n     * @param ConfigService $configService\n     */\n    public function __construct(Application $app, ConfigService $configService)\n    {\n        $this->app = $app;\n        $this->configService = $configService;\n\n        $this->trackers = new Collection();\n        $this->meta = new Collection();\n        $this->data = new Collection();\n    }\n\n    /**\n     * @return void\n     */\n    public function track(): void\n    {\n        $this->bootTrackers(Collection::make([\n            ApplicationTracker::class,\n            PerformanceTracker::class,\n            RequestTracker::class,\n            ResponseTracker::class,\n        ]));\n\n        $this->bootTrackers($this->configService->trackers());\n    }\n\n    /**\n     * @return void\n     */\n    public function terminate(): void\n    {\n        $this->trackers->each(function (Tracker $tracker) {\n            $tracker->terminate();\n            $this->meta = $this->meta->merge($tracker->meta());\n            $this->data = $this->data->merge($tracker->data());\n        });\n    }\n\n    /**\n     * @return Collection\n     */\n    public function meta(): Collection\n    {\n        return $this->meta;\n    }\n\n    /**\n     * @return Collection\n     */\n    public function data(): Collection\n    {\n        return $this->data;\n    }\n\n    /**\n     * @param Collection $trackers\n     * @return void\n     */\n    protected function bootTrackers(Collection $trackers): void\n    {\n        $trackers->each(function (string $tracker) {\n            $this->trackers->push($this->app->make($tracker));\n        });\n    }\n}\n"
  },
  {
    "path": "src/LaravelExecution/ConsoleFinishedRequest.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\LaravelExecution;\n\nuse Illuminate\\Support\\Collection;\nuse Symfony\\Component\\Console\\Input\\InputInterface;\nuse JKocik\\Laravel\\Profiler\\Contracts\\ExecutionRequest;\n\nclass ConsoleFinishedRequest implements ExecutionRequest\n{\n    /**\n     * @var null|string\n     */\n    protected $command;\n\n    /**\n     * @var InputInterface\n     */\n    protected $input;\n\n    /**\n     * ConsoleFinishedRequest constructor.\n     * @param null|string $command\n     * @param InputInterface $input\n     */\n    public function __construct(?string $command, InputInterface $input)\n    {\n        $this->command = $command;\n        $this->input = $input;\n    }\n\n    /**\n     * @return Collection\n     */\n    public function meta(): Collection\n    {\n        return Collection::make([\n            'type' => 'command-finished',\n            'path' => $this->command,\n        ]);\n    }\n\n    /**\n     * @return Collection\n     */\n    public function data(): Collection\n    {\n        return Collection::make([\n            'arguments' => $this->input->getArguments(),\n            'options' => $this->input->getOptions(),\n        ]);\n    }\n}\n"
  },
  {
    "path": "src/LaravelExecution/ConsoleFinishedResponse.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\LaravelExecution;\n\nuse Illuminate\\Support\\Collection;\nuse JKocik\\Laravel\\Profiler\\Contracts\\ExecutionResponse;\n\nclass ConsoleFinishedResponse implements ExecutionResponse\n{\n    /**\n     * @var int\n     */\n    protected $exitCode;\n\n    /**\n     * ConsoleFinishedResponse constructor.\n     * @param int $exitCode\n     */\n    public function __construct(int $exitCode)\n    {\n        $this->exitCode = $exitCode;\n    }\n\n    /**\n     * @return Collection\n     */\n    public function meta(): Collection\n    {\n        return Collection::make([\n            'status' => $this->exitCode,\n        ]);\n    }\n\n    /**\n     * @return Collection\n     */\n    public function data(): Collection\n    {\n        return Collection::make();\n    }\n}\n"
  },
  {
    "path": "src/LaravelExecution/ConsoleStartingRequest.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\LaravelExecution;\n\nuse Illuminate\\Support\\Collection;\nuse JKocik\\Laravel\\Profiler\\Contracts\\ExecutionRequest;\n\nclass ConsoleStartingRequest implements ExecutionRequest\n{\n    /**\n     * @return Collection\n     */\n    public function meta(): Collection\n    {\n        return Collection::make([\n            'type' => 'command-starting',\n        ]);\n    }\n\n    /**\n     * @return Collection\n     */\n    public function data(): Collection\n    {\n        return Collection::make();\n    }\n}\n"
  },
  {
    "path": "src/LaravelExecution/ConsoleStartingResponse.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\LaravelExecution;\n\nuse Illuminate\\Support\\Collection;\nuse JKocik\\Laravel\\Profiler\\Contracts\\ExecutionResponse;\n\nclass ConsoleStartingResponse implements ExecutionResponse\n{\n    /**\n     * @return Collection\n     */\n    public function meta(): Collection\n    {\n        return Collection::make([\n            'status' => null,\n        ]);\n    }\n\n    /**\n     * @return Collection\n     */\n    public function data(): Collection\n    {\n        return Collection::make();\n    }\n}\n"
  },
  {
    "path": "src/LaravelExecution/ExceptionHandlerFromVersion7.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\LaravelExecution;\n\nuse Throwable;\nuse App\\Exceptions\\Handler;\nuse JKocik\\Laravel\\Profiler\\Events\\ExceptionHandling;\n\nclass ExceptionHandlerFromVersion7 extends Handler\n{\n    /**\n     * @param Throwable $exception\n     * @return void\n     */\n    public function report(Throwable $exception)\n    {\n        event(new ExceptionHandling($exception));\n\n        parent::report($exception);\n    }\n}\n"
  },
  {
    "path": "src/LaravelExecution/ExceptionHandlerTillVersion6.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\LaravelExecution;\n\nuse Exception;\nuse App\\Exceptions\\Handler;\nuse JKocik\\Laravel\\Profiler\\Events\\ExceptionHandling;\n\nclass ExceptionHandlerTillVersion6 extends Handler\n{\n    /**\n     * @param Exception $exception\n     * @return void\n     */\n    public function report(Exception $exception)\n    {\n        event(new ExceptionHandling($exception));\n\n        parent::report($exception);\n    }\n}\n"
  },
  {
    "path": "src/LaravelExecution/HttpContent.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\LaravelExecution;\n\nuse Illuminate\\Support\\Collection;\nuse Symfony\\Component\\HttpFoundation\\Response;\nuse JKocik\\Laravel\\Profiler\\Contracts\\ExecutionContent;\n\nclass HttpContent implements ExecutionContent\n{\n    /**\n     * @var Response\n     */\n    protected $response;\n\n    /**\n     * HttpContent constructor.\n     * @param Response $response\n     */\n    public function __construct(Response $response)\n    {\n        $this->response = $response;\n    }\n\n    /**\n     * @return Collection\n     */\n    public function meta(): Collection\n    {\n        return Collection::make();\n    }\n\n    /**\n     * @return Collection\n     */\n    public function data(): Collection\n    {\n        return Collection::make([\n            'content' => $this->response->getContent(),\n        ]);\n    }\n}\n"
  },
  {
    "path": "src/LaravelExecution/HttpRequest.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\LaravelExecution;\n\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Http\\UploadedFile;\nuse Illuminate\\Support\\Collection;\nuse JKocik\\Laravel\\Profiler\\Contracts\\ExecutionRequest;\n\nclass HttpRequest implements ExecutionRequest\n{\n    /**\n     * @var Request\n     */\n    protected $request;\n\n    /**\n     * HttpRequest constructor.\n     * @param Request $request\n     */\n    public function __construct(Request $request)\n    {\n        $this->request = $request;\n    }\n\n    /**\n     * @return Collection\n     */\n    public function meta(): Collection\n    {\n        return Collection::make([\n            'type' => 'http',\n            'method' => $this->request->method(),\n            'path' => $this->request->path(),\n            'ajax' => $this->request->ajax(),\n            'json' => $this->request->isJson(),\n        ]);\n    }\n\n    /**\n     * @return Collection\n     */\n    public function data(): Collection\n    {\n        return Collection::make([\n            'pjax' => $this->request->pjax(),\n            'url' => $this->request->url(),\n            'query' => $this->request->query(),\n            'ip' => $this->request->ip(),\n            'header' => $this->request->header(),\n            'input' => $this->request->input(),\n            'files' => $this->files(),\n            'cookie' => $this->request->cookie(),\n        ]);\n    }\n\n    /**\n     * @return Collection\n     */\n    protected function files(): Collection\n    {\n        $files = Collection::make($this->request->allFiles());\n\n        return $this->filesMap($files);\n    }\n\n    /**\n     * @param Collection $files\n     * @return Collection\n     */\n    protected function filesMap(Collection $files): Collection\n    {\n        return $files->map(function ($file) {\n            if (is_array($file)) {\n                $files = Collection::make($file);\n                return $this->filesMap($files);\n            }\n\n            return [get_class($file) => $this->file($file)];\n        });\n    }\n\n    /**\n     * @param UploadedFile $file\n     * @return array\n     */\n    protected function file(UploadedFile $file): array\n    {\n        return [\n            'client original name' => $file->getClientOriginalName(),\n            'client original extension' => $file->getClientOriginalExtension(),\n            'client mime type' => $file->getClientMimeType(),\n            'client size' => $this->clientSize($file),\n            'path' => $file->path(),\n        ];\n    }\n\n    /**\n     * @param UploadedFile $file\n     * @return int\n     */\n    protected function clientSize(UploadedFile $file): int\n    {\n        return method_exists($file, 'getClientSize')\n            ? $file->getClientSize()\n            : $file->getSize();\n    }\n}\n"
  },
  {
    "path": "src/LaravelExecution/HttpResponse.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\LaravelExecution;\n\nuse Illuminate\\Support\\Collection;\nuse Symfony\\Component\\HttpFoundation\\Response;\nuse JKocik\\Laravel\\Profiler\\Contracts\\ExecutionResponse;\n\nclass HttpResponse implements ExecutionResponse\n{\n    /**\n     * @var Response\n     */\n    protected $response;\n\n    /**\n     * HttpResponse constructor.\n     * @param Response $response\n     */\n    public function __construct(Response $response)\n    {\n        $this->response = $response;\n    }\n\n    /**\n     * @return Collection\n     */\n    public function meta(): Collection\n    {\n        return Collection::make([\n            'status' => $this->response->getStatusCode(),\n            'status_text' => $this->getStatusText(),\n        ]);\n    }\n\n    /**\n     * @return Collection\n     */\n    public function data(): Collection\n    {\n        return Collection::make([\n            'headers' => $this->response->headers->all(),\n        ]);\n    }\n\n    /**\n     * @return string\n     */\n    protected function getStatusText(): string\n    {\n        return $this->response::$statusTexts[$this->response->getStatusCode()] ?? 'unknown status';\n    }\n}\n"
  },
  {
    "path": "src/LaravelExecution/HttpRoute.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\LaravelExecution;\n\nuse Closure;\nuse ReflectionMethod;\nuse ReflectionFunction;\nuse ReflectionException;\nuse ReflectionParameter;\nuse Illuminate\\Routing\\Route;\nuse Illuminate\\Support\\Collection;\nuse Illuminate\\Foundation\\Http\\FormRequest;\nuse JKocik\\Laravel\\Profiler\\Contracts\\ExecutionRoute;\n\nclass HttpRoute implements ExecutionRoute\n{\n    /**\n     * @var Route\n     */\n    protected $route;\n\n    /**\n     * HttpRoute constructor.\n     * @param Route $route\n     */\n    public function __construct(Route $route)\n    {\n        $this->route = $route;\n    }\n\n    /**\n     * @return Collection\n     */\n    public function meta(): Collection\n    {\n        return Collection::make();\n    }\n\n    /**\n     * @return Collection\n     */\n    public function data(): Collection\n    {\n        return Collection::make([\n            'methods' => $this->route->methods(),\n            'uri' => $this->route->uri(),\n            'name' => $this->route->getName(),\n            'middleware' => $this->route->middleware(),\n            'parameters' => $this->route->parameters(),\n            'prefix' => $this->route->getPrefix(),\n            'uses' => $this->uses(),\n        ]);\n    }\n\n    /**\n     * @return array\n     */\n    protected function uses(): array\n    {\n        $uses = $this->route->getAction();\n\n        try {\n            if ($this->isClosureIn($uses)) {\n                return $this->closure($uses);\n            }\n\n            if ($this->isControllerIn($uses)) {\n                return $this->controller($uses);\n            }\n        } catch (ReflectionException $e) {}\n\n        return [];\n    }\n\n    /**\n     * @param array $uses\n     * @return bool\n     */\n    protected function isClosureIn(array $uses): bool\n    {\n        return isset($uses['uses']) && $uses['uses'] instanceof Closure;\n    }\n\n    /**\n     * @param array $uses\n     * @return array\n     */\n    protected function closure(array $uses): array\n    {\n        $action = new ReflectionFunction($uses['uses']);\n\n        return [\n            'closure' => $action->getFileName() . ':' . $action->getStartLine() . '-' . $action->getEndLine(),\n            'form_request' => $this->formRequest($action->getParameters()),\n        ];\n    }\n\n    /**\n     * @param array $uses\n     * @return bool\n     */\n    protected function isControllerIn(array $uses): bool\n    {\n        return isset($uses['uses']) && count(explode('@', $uses['uses'])) == 2;\n    }\n\n    /**\n     * @param array $uses\n     * @return array\n     */\n    protected function controller(array $uses): array\n    {\n        list($controller, $method) = explode('@', $uses['uses']);\n\n        $action = new ReflectionMethod($controller, $method);\n\n        return [\n            'controller' => $uses['uses'] . ':' . $action->getStartLine() . '-' . $action->getEndLine(),\n            'form_request' => $this->formRequest($action->getParameters()),\n        ];\n    }\n\n    /**\n     * @param array $parameters\n     * @return string\n     */\n    protected function formRequest(array $parameters): string\n    {\n        $formRequest = Collection::make($parameters)->filter(function (ReflectionParameter $parameter) {\n            return $parameter->getType() && is_subclass_of($parameter->getType()->getName(), FormRequest::class);\n        })->first();\n\n        return $formRequest ? $formRequest->getType()->getName() : '';\n    }\n}\n"
  },
  {
    "path": "src/LaravelExecution/HttpServer.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\LaravelExecution;\n\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Support\\Collection;\nuse JKocik\\Laravel\\Profiler\\Contracts\\ExecutionServer;\n\nclass HttpServer implements ExecutionServer\n{\n    /**\n     * @var Request\n     */\n    protected $request;\n\n    /**\n     * HttpServer constructor.\n     * @param Request $request\n     */\n    public function __construct(Request $request)\n    {\n        $this->request = $request;\n    }\n\n    /**\n     * @return Collection\n     */\n    public function meta(): Collection\n    {\n        return Collection::make();\n    }\n\n    /**\n     * @return Collection\n     */\n    public function data(): Collection\n    {\n        return Collection::make(\n            $this->request->server()\n        );\n    }\n}\n"
  },
  {
    "path": "src/LaravelExecution/HttpSession.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\LaravelExecution;\n\nuse Illuminate\\Support\\Collection;\nuse Illuminate\\Session\\SessionManager;\nuse JKocik\\Laravel\\Profiler\\Contracts\\ExecutionSession;\n\nclass HttpSession implements ExecutionSession\n{\n    /**\n     * @var SessionManager\n     */\n    protected $session;\n\n    /**\n     * HttpSession constructor.\n     * @param SessionManager $session\n     */\n    public function __construct(SessionManager $session)\n    {\n        $this->session = $session;\n    }\n\n    /**\n     * @return Collection\n     */\n    public function meta(): Collection\n    {\n        return Collection::make();\n    }\n\n    /**\n     * @return Collection\n     */\n    public function data(): Collection\n    {\n        return Collection::make($this->session->all());\n    }\n}\n"
  },
  {
    "path": "src/LaravelExecution/LaravelExecutionData.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\LaravelExecution;\n\nuse JKocik\\Laravel\\Profiler\\Contracts\\ExecutionData;\nuse JKocik\\Laravel\\Profiler\\Contracts\\ExecutionRoute;\nuse JKocik\\Laravel\\Profiler\\Contracts\\ExecutionServer;\nuse JKocik\\Laravel\\Profiler\\Contracts\\ExecutionRequest;\nuse JKocik\\Laravel\\Profiler\\Contracts\\ExecutionContent;\nuse JKocik\\Laravel\\Profiler\\Contracts\\ExecutionSession;\nuse JKocik\\Laravel\\Profiler\\Contracts\\ExecutionResponse;\n\nclass LaravelExecutionData implements ExecutionData\n{\n    /**\n     * @var ExecutionRequest\n     */\n    protected $request;\n\n    /**\n     * @var ExecutionRoute\n     */\n    protected $route;\n\n    /**\n     * @var ExecutionSession\n     */\n    protected $session;\n\n    /**\n     * @var ExecutionServer\n     */\n    protected $server;\n\n    /**\n     * @var ExecutionResponse\n     */\n    protected $response;\n\n    /**\n     * @var ExecutionContent\n     */\n    protected $content;\n\n    /**\n     * LaravelExecutionData constructor.\n     */\n    public function __construct()\n    {\n        $this->setRequest(new NullRequest());\n        $this->setRoute(new NullRoute());\n        $this->setSession(new NullSession());\n        $this->setServer(new NullServer());\n        $this->setResponse(new NullResponse());\n        $this->setContent(new NullContent());\n    }\n\n    /**\n     * @param ExecutionRequest $request\n     * @return void\n     */\n    public function setRequest(ExecutionRequest $request): void\n    {\n        $this->request = $request;\n    }\n\n    /**\n     * @return ExecutionRequest\n     */\n    public function request(): ExecutionRequest\n    {\n        return $this->request;\n    }\n\n    /**\n     * @param ExecutionRoute $route\n     * @return void\n     */\n    public function setRoute(ExecutionRoute $route): void\n    {\n        $this->route = $route;\n    }\n\n    /**\n     * @return ExecutionRoute\n     */\n    public function route(): ExecutionRoute\n    {\n        return $this->route;\n    }\n\n    /**\n     * @param ExecutionSession $session\n     * @return void\n     */\n    public function setSession(ExecutionSession $session): void\n    {\n        $this->session = $session;\n    }\n\n    /**\n     * @return ExecutionSession\n     */\n    public function session(): ExecutionSession\n    {\n        return $this->session;\n    }\n\n    /**\n     * @param ExecutionServer $server\n     * @return void\n     */\n    public function setServer(ExecutionServer $server): void\n    {\n        $this->server = $server;\n    }\n\n    /**\n     * @return ExecutionServer\n     */\n    public function server(): ExecutionServer\n    {\n        return $this->server;\n    }\n\n    /**\n     * @param ExecutionResponse $response\n     * @return void\n     */\n    public function setResponse(ExecutionResponse $response): void\n    {\n        $this->response = $response;\n    }\n\n    /**\n     * @return ExecutionResponse\n     */\n    public function response(): ExecutionResponse\n    {\n        return $this->response;\n    }\n\n    /**\n     * @param ExecutionContent $content\n     * @return void\n     */\n    public function setContent(ExecutionContent $content): void\n    {\n        $this->content = $content;\n    }\n\n    /**\n     * @return ExecutionContent\n     */\n    public function content(): ExecutionContent\n    {\n        return $this->content;\n    }\n}\n"
  },
  {
    "path": "src/LaravelExecution/NullContent.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\LaravelExecution;\n\nuse Illuminate\\Support\\Collection;\nuse JKocik\\Laravel\\Profiler\\Contracts\\ExecutionContent;\n\nclass NullContent implements ExecutionContent\n{\n    /**\n     * @return Collection\n     */\n    public function meta(): Collection\n    {\n        return Collection::make();\n    }\n\n    /**\n     * @return Collection\n     */\n    public function data(): Collection\n    {\n        return Collection::make();\n    }\n}\n"
  },
  {
    "path": "src/LaravelExecution/NullRequest.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\LaravelExecution;\n\nuse Illuminate\\Support\\Collection;\nuse JKocik\\Laravel\\Profiler\\Contracts\\ExecutionRequest;\n\nclass NullRequest implements ExecutionRequest\n{\n    /**\n     * @return Collection\n     */\n    public function meta(): Collection\n    {\n        return Collection::make([\n            'type' => null,\n        ]);\n    }\n\n    /**\n     * @return Collection\n     */\n    public function data(): Collection\n    {\n        return Collection::make();\n    }\n}\n"
  },
  {
    "path": "src/LaravelExecution/NullResponse.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\LaravelExecution;\n\nuse Illuminate\\Support\\Collection;\nuse JKocik\\Laravel\\Profiler\\Contracts\\ExecutionResponse;\n\nclass NullResponse implements ExecutionResponse\n{\n    /**\n     * @return Collection\n     */\n    public function meta(): Collection\n    {\n        return Collection::make();\n    }\n\n    /**\n     * @return Collection\n     */\n    public function data(): Collection\n    {\n        return Collection::make();\n    }\n}\n"
  },
  {
    "path": "src/LaravelExecution/NullRoute.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\LaravelExecution;\n\nuse Illuminate\\Support\\Collection;\nuse JKocik\\Laravel\\Profiler\\Contracts\\ExecutionRoute;\n\nclass NullRoute implements ExecutionRoute\n{\n    /**\n     * @return Collection\n     */\n    public function meta(): Collection\n    {\n        return Collection::make();\n    }\n\n    /**\n     * @return Collection\n     */\n    public function data(): Collection\n    {\n        return Collection::make();\n    }\n}\n"
  },
  {
    "path": "src/LaravelExecution/NullServer.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\LaravelExecution;\n\nuse Illuminate\\Support\\Collection;\nuse JKocik\\Laravel\\Profiler\\Contracts\\ExecutionServer;\n\nclass NullServer implements ExecutionServer\n{\n    /**\n     * @return Collection\n     */\n    public function meta(): Collection\n    {\n        return Collection::make();\n    }\n\n    /**\n     * @return Collection\n     */\n    public function data(): Collection\n    {\n        return Collection::make();\n    }\n}\n"
  },
  {
    "path": "src/LaravelExecution/NullSession.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\LaravelExecution;\n\nuse Illuminate\\Support\\Collection;\nuse JKocik\\Laravel\\Profiler\\Contracts\\ExecutionSession;\n\nclass NullSession implements ExecutionSession\n{\n    /**\n     * @return Collection\n     */\n    public function meta(): Collection\n    {\n        return Collection::make();\n    }\n\n    /**\n     * @return Collection\n     */\n    public function data(): Collection\n    {\n        return Collection::make();\n    }\n}\n"
  },
  {
    "path": "src/LaravelExecutionWatcher.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler;\n\nuse JKocik\\Laravel\\Profiler\\Contracts\\ExecutionWatcher;\nuse JKocik\\Laravel\\Profiler\\LaravelListeners\\HttpRequestHandledListener;\nuse JKocik\\Laravel\\Profiler\\LaravelListeners\\ConsoleCommandFinishedListener;\n\nclass LaravelExecutionWatcher implements ExecutionWatcher\n{\n    /**\n     * @var HttpRequestHandledListener\n     */\n    protected $httpRequestHandledListener;\n\n    /**\n     * @var ConsoleCommandFinishedListener\n     */\n    protected $consoleCommandFinishedListener;\n\n    /**\n     * LaravelExecutionWatcher constructor.\n     * @param HttpRequestHandledListener $httpRequestHandledListener\n     * @param ConsoleCommandFinishedListener $consoleCommandFinishedListener\n     */\n    public function __construct(\n        HttpRequestHandledListener $httpRequestHandledListener,\n        ConsoleCommandFinishedListener $consoleCommandFinishedListener\n    ) {\n        $this->httpRequestHandledListener = $httpRequestHandledListener;\n        $this->consoleCommandFinishedListener = $consoleCommandFinishedListener;\n    }\n\n    /**\n     * @return void\n     */\n    public function watch(): void\n    {\n        $this->httpRequestHandledListener->listen();\n        $this->consoleCommandFinishedListener->listen();\n    }\n}\n"
  },
  {
    "path": "src/LaravelListeners/AuthListener.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\LaravelListeners;\n\nuse Illuminate\\Auth\\Events\\Logout;\nuse Illuminate\\Support\\Facades\\Auth;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse JKocik\\Laravel\\Profiler\\Contracts\\LaravelListener;\n\nclass AuthListener implements LaravelListener\n{\n    /**\n     * @var User\n     */\n    protected $user;\n\n    /**\n     * @return void\n     */\n    public function listen(): void\n    {\n        Event::listen(Logout::class, function (Logout $logout) {\n            $this->user = $logout->user;\n        });\n    }\n\n    /**\n     * @return User|null\n     */\n    public function user(): ?Model\n    {\n        return $this->user ?? Auth::user();\n    }\n}\n"
  },
  {
    "path": "src/LaravelListeners/ConsoleCommandFinishedListener.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\LaravelListeners;\n\nuse Illuminate\\Support\\Facades\\Event;\nuse JKocik\\Laravel\\Profiler\\Contracts\\ExecutionData;\nuse JKocik\\Laravel\\Profiler\\Contracts\\LaravelListener;\nuse JKocik\\Laravel\\Profiler\\LaravelExecution\\ConsoleStartingRequest;\nuse JKocik\\Laravel\\Profiler\\LaravelExecution\\ConsoleFinishedRequest;\nuse JKocik\\Laravel\\Profiler\\LaravelExecution\\ConsoleStartingResponse;\nuse JKocik\\Laravel\\Profiler\\LaravelExecution\\ConsoleFinishedResponse;\n\nclass ConsoleCommandFinishedListener implements LaravelListener\n{\n    /**\n     * @var ExecutionData\n     */\n    protected $executionData;\n\n    /**\n     * ConsoleCommandFinishedListener constructor.\n     * @param ExecutionData $executionData\n     */\n    public function __construct(ExecutionData $executionData)\n    {\n        $this->executionData = $executionData;\n    }\n\n    /**\n     * @return void\n     */\n    public function listen(): void\n    {\n        Event::listen(\\Illuminate\\Console\\Events\\ArtisanStarting::class, function ($event) {\n            $this->executionData->setRequest(new ConsoleStartingRequest());\n            $this->executionData->setResponse(new ConsoleStartingResponse());\n        });\n\n        Event::listen(\\Illuminate\\Console\\Events\\CommandFinished::class, function ($event) {\n            $this->executionData->setRequest(new ConsoleFinishedRequest($event->command, $event->input));\n            $this->executionData->setResponse(new ConsoleFinishedResponse($event->exitCode));\n        });\n    }\n}\n"
  },
  {
    "path": "src/LaravelListeners/EventsListener.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\LaravelListeners;\n\nuse Illuminate\\Events\\Dispatcher;\nuse Illuminate\\Support\\Collection;\nuse JKocik\\Laravel\\Profiler\\Events\\ResetTrackers;\nuse JKocik\\Laravel\\Profiler\\Services\\ConfigService;\nuse JKocik\\Laravel\\Profiler\\Contracts\\LaravelListener;\n\nclass EventsListener implements LaravelListener\n{\n    /**\n     * @var Dispatcher\n     */\n    protected $dispatcher;\n\n    /**\n     * @var ConfigService\n     */\n    protected $configService;\n\n    /**\n     * @var array\n     */\n    protected $events = [];\n\n    /**\n     * @var string\n     */\n    protected $previousEventName = '';\n\n    /**\n     * @var int\n     */\n    protected $count = 0;\n\n    /**\n     * EventsListener constructor.\n     * @param Dispatcher $dispatcher\n     * @param ConfigService $configService\n     */\n    public function __construct(Dispatcher $dispatcher, ConfigService $configService)\n    {\n        $this->dispatcher = $dispatcher;\n        $this->configService = $configService;\n    }\n\n    /**\n     * @return void\n     */\n    public function listen(): void\n    {\n        $this->listenEvents();\n        $this->listenResetTrackers();\n    }\n\n    /**\n     * @return Collection\n     */\n    public function events(): Collection\n    {\n        return Collection::make($this->events);\n    }\n\n    /**\n     * @return int\n     */\n    public function count(): int\n    {\n        return $this->count;\n    }\n\n    /**\n     * @return void\n     */\n    protected function listenEvents(): void\n    {\n        $this->dispatcher->listen('*', function ($event, $payload = null) {\n            $name = $this->resolveName($event, $payload);\n\n            if ($this->shouldSkip($name)) {\n                return;\n            }\n\n            $this->count++;\n\n            if ($this->shouldGroup($name)) {\n                return $this->groupToPreviousEvent();\n            }\n\n            $this->previousEventName = $name;\n\n            array_push($this->events, $this->resolveEvent($name, $event, $payload));\n        });\n    }\n\n    /**\n     * @return void\n     */\n    protected function listenResetTrackers(): void\n    {\n        $this->dispatcher->listen(ResetTrackers::class, function () {\n            $this->events = [];\n            $this->previousEventName = '';\n            $this->count = 0;\n        });\n    }\n\n    /**\n     * @param string $name\n     * @param $event\n     * @param $payload\n     * @return array\n     */\n    protected function resolveEvent(string $name, $event, $payload): array\n    {\n        if ($this->configService->isEventsDataEnabled()) {\n            return [$event, $payload, $name, 1];\n        }\n\n        return [null, null, $name, 1];\n    }\n\n    /**\n     * @param $event\n     * @param $payload\n     * @return string\n     */\n    protected function resolveName($event, $payload): string\n    {\n        return is_array($payload) ? $event : $this->dispatcher->firing();\n    }\n\n    /**\n     * @param string $name\n     * @return bool\n     */\n    protected function shouldGroup(string $name): bool\n    {\n        return $this->configService->isEventsGroupEnabled() && $name == $this->previousEventName;\n    }\n\n    /**\n     * @return void\n     */\n    protected function groupToPreviousEvent(): void\n    {\n        $this->events[count($this->events) - 1][3]++;\n    }\n\n    /**\n     * @param string $name\n     * @return bool\n     */\n    protected function shouldSkip(string $name): bool\n    {\n        $shouldSkip = Collection::make([\n            'bootstrapped: ' . \\Illuminate\\Foundation\\Bootstrap\\BootProviders::class,\n            \\JKocik\\Laravel\\Profiler\\Events\\ExceptionHandling::class,\n            \\JKocik\\Laravel\\Profiler\\Events\\ProfilerBound::class,\n            \\JKocik\\Laravel\\Profiler\\Events\\ResetTrackers::class,\n            \\JKocik\\Laravel\\Profiler\\Events\\Terminating::class,\n            \\JKocik\\Laravel\\Profiler\\Events\\Tracking::class,\n        ]);\n\n        return $shouldSkip->contains($name);\n    }\n}\n"
  },
  {
    "path": "src/LaravelListeners/ExceptionListener.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\LaravelListeners;\n\nuse Throwable;\nuse Illuminate\\Support\\Facades\\Event;\nuse JKocik\\Laravel\\Profiler\\Events\\ExceptionHandling;\nuse JKocik\\Laravel\\Profiler\\Contracts\\LaravelListener;\n\nclass ExceptionListener implements LaravelListener\n{\n    /**\n     * @var Throwable\n     */\n    protected $exception;\n\n    /**\n     * @return void\n     */\n    public function listen(): void\n    {\n        Event::listen(ExceptionHandling::class, function (ExceptionHandling $exceptionHandling) {\n            $this->exception = $exceptionHandling->exception;\n        });\n    }\n\n    public function exception(): ?Throwable\n    {\n        return $this->exception;\n    }\n}\n"
  },
  {
    "path": "src/LaravelListeners/HttpRequestHandledListener.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\LaravelListeners;\n\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Support\\Facades\\Event;\nuse Symfony\\Component\\HttpFoundation\\Response;\nuse JKocik\\Laravel\\Profiler\\Contracts\\ExecutionData;\nuse JKocik\\Laravel\\Profiler\\Contracts\\ExecutionRoute;\nuse JKocik\\Laravel\\Profiler\\Contracts\\LaravelListener;\nuse JKocik\\Laravel\\Profiler\\LaravelExecution\\NullRoute;\nuse JKocik\\Laravel\\Profiler\\LaravelExecution\\HttpRoute;\nuse JKocik\\Laravel\\Profiler\\LaravelExecution\\HttpServer;\nuse JKocik\\Laravel\\Profiler\\LaravelExecution\\HttpSession;\nuse JKocik\\Laravel\\Profiler\\LaravelExecution\\HttpContent;\nuse JKocik\\Laravel\\Profiler\\LaravelExecution\\HttpRequest;\nuse JKocik\\Laravel\\Profiler\\LaravelExecution\\HttpResponse;\n\nclass HttpRequestHandledListener implements LaravelListener\n{\n    /**\n     * @var ExecutionData\n     */\n    protected $executionData;\n\n    /**\n     * HttpRequestHandledListener constructor.\n     * @param ExecutionData $executionData\n     */\n    public function __construct(ExecutionData $executionData)\n    {\n        $this->executionData = $executionData;\n    }\n\n    /**\n     * @return void\n     */\n    public function listen(): void\n    {\n        /** @codeCoverageIgnoreStart */\n        Event::listen('kernel.handled', function (Request $request, Response $response) {\n            $this->executionData->setRequest(new HttpRequest($request));\n            $this->executionData->setRoute($this->routeOf($request));\n            $this->executionData->setSession(new HttpSession(session()));\n            $this->executionData->setServer(new HttpServer($request));\n            $this->executionData->setResponse(new HttpResponse($response));\n            $this->executionData->setContent(new HttpContent($response));\n        });\n        /** @codeCoverageIgnoreEnd */\n\n        Event::listen(\\Illuminate\\Foundation\\Http\\Events\\RequestHandled::class, function ($event) {\n            $this->executionData->setRequest(new HttpRequest($event->request));\n            $this->executionData->setRoute($this->routeOf($event->request));\n            $this->executionData->setSession(new HttpSession(session()));\n            $this->executionData->setServer(new HttpServer($event->request));\n            $this->executionData->setResponse(new HttpResponse($event->response));\n            $this->executionData->setContent(new HttpContent($event->response));\n        });\n    }\n\n    /**\n     * @param Request $request\n     * @return ExecutionRoute\n     */\n    protected function routeOf(Request $request): ExecutionRoute\n    {\n        return $request->route() ? new HttpRoute($request->route()) : new NullRoute();\n    }\n}\n"
  },
  {
    "path": "src/LaravelListeners/PerformanceListener.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\LaravelListeners;\n\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Foundation\\Application;\nuse Illuminate\\Routing\\Events\\RouteMatched;\nuse JKocik\\Laravel\\Profiler\\Events\\Tracking;\nuse JKocik\\Laravel\\Profiler\\Contracts\\Timer;\nuse JKocik\\Laravel\\Profiler\\Contracts\\Memory;\nuse Illuminate\\Console\\Events\\ArtisanStarting;\nuse JKocik\\Laravel\\Profiler\\Events\\Terminating;\nuse Illuminate\\Foundation\\Http\\Events\\RequestHandled;\nuse JKocik\\Laravel\\Profiler\\Contracts\\LaravelListener;\n\nclass PerformanceListener implements LaravelListener\n{\n    /**\n     * @var Application\n     */\n    protected $app;\n\n    /**\n     * @var Timer\n     */\n    protected $timer;\n\n    /**\n     * @var Memory\n     */\n    protected $memory;\n\n    /**\n     * PerformanceListener constructor.\n     * @param Application $app\n     * @param Timer $timer\n     * @param Memory $memory\n     */\n    public function __construct(\n        Application $app,\n        Timer $timer,\n        Memory $memory\n    ) {\n        $this->app = $app;\n        $this->timer = $timer;\n        $this->memory = $memory;\n    }\n\n    /**\n     * @return void\n     */\n    public function listen(): void\n    {\n        $this->listenHttp();\n        $this->listenConsole();\n    }\n\n    /**\n     * @return void\n     */\n    protected function listenHttp(): void\n    {\n        Event::listen(Tracking::class, function () {\n            $this->timer->startLaravel();\n        });\n\n        $this->app->booting(function () {\n            $this->timer->start('boot');\n        });\n\n        $this->app->booted(function () {\n            $this->timer->finish('boot');\n            $this->timer->start($this->resolveRouteName());\n        });\n\n        Event::listen(RouteMatched::class, function () {\n            $this->timer->finish($this->resolveRouteName());\n            $this->timer->start('request');\n        });\n\n        /** @codeCoverageIgnoreStart */\n        Event::listen('kernel.handled', function () {\n            $this->timer->finish('request');\n            $this->timer->start('response');\n        });\n        /** @codeCoverageIgnoreEnd */\n\n        Event::listen(RequestHandled::class, function () {\n            $this->timer->finish('request');\n            $this->timer->start('response');\n        });\n\n        Event::listen(Terminating::class, function () {\n            $this->memory->recordPeak();\n            $this->timer->finish('response');\n            $this->timer->finishLaravel();\n        });\n    }\n\n    /**\n     * @return void\n     */\n    protected function listenConsole(): void\n    {\n        Event::listen(ArtisanStarting::class, function () {\n            $this->timer->start('command');\n        });\n\n        Event::listen(Terminating::class, function () {\n            $this->timer->finish('command');\n        });\n    }\n\n    /**\n     * @return string\n     */\n    protected function resolveRouteName(): string\n    {\n        if ($this->app->runningUnitTests()) {\n            return 'setup';\n        }\n\n        return 'route';\n    }\n}\n"
  },
  {
    "path": "src/LaravelListeners/QueriesListener.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\LaravelListeners;\n\nuse Illuminate\\Support\\Collection;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Database\\Events\\QueryExecuted;\nuse JKocik\\Laravel\\Profiler\\Events\\ResetTrackers;\nuse Illuminate\\Database\\Events\\TransactionBeginning;\nuse Illuminate\\Database\\Events\\TransactionCommitted;\nuse Illuminate\\Database\\Events\\TransactionRolledBack;\nuse JKocik\\Laravel\\Profiler\\Contracts\\LaravelListener;\n\nclass QueriesListener implements LaravelListener\n{\n    /**\n     * @var array\n     */\n    protected $queries = [];\n\n    /**\n     * @var int\n     */\n    protected $count = 0;\n\n    /**\n     * @return void\n     */\n    public function listen(): void\n    {\n        $this->listenQueries();\n        $this->listenTransactions();\n        $this->listenResetTrackers();\n    }\n\n    /**\n     * @return Collection\n     */\n    public function queries(): Collection\n    {\n        return Collection::make($this->queries);\n    }\n\n    /**\n     * @return int\n     */\n    public function count(): int\n    {\n        return $this->count;\n    }\n\n    /**\n     * @return void\n     */\n    protected function listenQueries(): void\n    {\n        Event::listen(QueryExecuted::class, function (QueryExecuted $event) {\n            $this->count++;\n\n            list($bindings, $bindingsQuoted) = $this->formatBindings($event);\n\n            array_push($this->queries, [\n                'query',\n                $event->sql,\n                $event->time,\n                $event->connection->getDatabaseName(),\n                $event->connectionName,\n                $bindings,\n                $bindingsQuoted,\n            ]);\n        });\n    }\n\n    /**\n     * @return void\n     */\n    protected function listenTransactions(): void\n    {\n        Event::listen(TransactionBeginning::class, function (TransactionBeginning $event) {\n            array_push($this->queries, [\n                'transaction-begin',\n                $event->connection->getDatabaseName(),\n                $event->connectionName,\n            ]);\n        });\n\n        Event::listen(TransactionCommitted::class, function (TransactionCommitted $event) {\n            array_push($this->queries, [\n                'transaction-commit',\n                $event->connection->getDatabaseName(),\n                $event->connectionName,\n            ]);\n        });\n\n        Event::listen(TransactionRolledBack::class, function (TransactionRolledBack $event) {\n            array_push($this->queries, [\n                'transaction-rollback',\n                $event->connection->getDatabaseName(),\n                $event->connectionName,\n            ]);\n        });\n    }\n\n    /**\n     * @return void\n     */\n    protected function listenResetTrackers(): void\n    {\n        Event::listen(ResetTrackers::class, function () {\n            $this->queries = [];\n            $this->count = 0;\n        });\n    }\n\n    /**\n     * @param QueryExecuted $event\n     * @return array\n     */\n    protected function formatBindings(QueryExecuted $event): array\n    {\n        $preparedBindings = $event->connection->prepareBindings($event->bindings);\n\n        foreach ($preparedBindings as $key => $binding) {\n            $bindings[$key] = $this->truncate($binding);\n            $bindingsQuoted[$key] = $this->quote($event, $bindings[$key]);\n        }\n\n        return [\n            $bindings ?? [],\n            $bindingsQuoted ?? [],\n        ];\n    }\n\n    /**\n     * @param $binding\n     * @return mixed\n     */\n    protected function truncate($binding)\n    {\n        if (is_string($binding) && strlen($binding) > 255) {\n            return substr($binding, 0, 255) . '...{truncated}';\n        }\n\n        return $binding;\n    }\n\n    /**\n     * @param QueryExecuted $event\n     * @param $binding\n     * @return mixed\n     */\n    protected function quote(QueryExecuted $event, $binding)\n    {\n        if (is_int($binding) || is_float($binding) || is_object($binding)) {\n            return $binding;\n        }\n\n        return $event->connection->getPdo()->quote($binding);\n    }\n}\n"
  },
  {
    "path": "src/LaravelListeners/RedisListener.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\LaravelListeners;\n\nuse Illuminate\\Support\\Collection;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Redis\\Events\\CommandExecuted;\nuse JKocik\\Laravel\\Profiler\\Events\\ResetTrackers;\nuse JKocik\\Laravel\\Profiler\\Contracts\\LaravelListener;\n\nclass RedisListener implements LaravelListener\n{\n    /**\n     * @var array\n     */\n    protected $commands = [];\n\n    /**\n     * @var int\n     */\n    protected $count = 0;\n\n    /**\n     * @return void\n     */\n    public function listen(): void\n    {\n        $this->listenCommands();\n        $this->listenResetTrackers();\n    }\n\n    /**\n     * @return Collection\n     */\n    public function commands(): Collection\n    {\n        return Collection::make($this->commands);\n    }\n\n    /**\n     * @return int\n     */\n    public function count(): int\n    {\n        return $this->count;\n    }\n\n    /**\n     * @return void\n     */\n    protected function listenCommands(): void\n    {\n        Event::listen(CommandExecuted::class, function (CommandExecuted $event) {\n            $this->count++;\n\n            array_push($this->commands, [\n                $event->command,\n                $event->time,\n                $event->connectionName,\n                $event->parameters,\n            ]);\n        });\n    }\n\n    /**\n     * @return void\n     */\n    protected function listenResetTrackers(): void\n    {\n        Event::listen(ResetTrackers::class, function () {\n            $this->commands = [];\n            $this->count = 0;\n        });\n    }\n}\n"
  },
  {
    "path": "src/LaravelListeners/ViewsListener.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\LaravelListeners;\n\nuse Illuminate\\View\\View;\nuse Illuminate\\Support\\Collection;\nuse Illuminate\\Support\\Facades\\Event;\nuse JKocik\\Laravel\\Profiler\\Events\\ResetTrackers;\nuse JKocik\\Laravel\\Profiler\\Contracts\\LaravelListener;\n\nclass ViewsListener implements LaravelListener\n{\n    /**\n     * @var array\n     */\n    protected $views = [];\n\n    /**\n     * @return void\n     */\n    public function listen(): void\n    {\n        $this->listenViews();\n        $this->listenResetTrackers();\n    }\n\n    /**\n     * @return Collection\n     */\n    public function views(): Collection\n    {\n        return Collection::make($this->views);\n    }\n\n    /**\n     * @return void\n     */\n    protected function listenViews(): void\n    {\n        Event::listen('composing:*', function (...$view) {\n            array_push($this->views, $this->resolveView($view));\n        });\n    }\n\n    /**\n     * @return void\n     */\n    protected function listenResetTrackers(): void\n    {\n        Event::listen(ResetTrackers::class, function () {\n            $this->views = [];\n        });\n    }\n\n    /**\n     * @param array $view\n     * @return View\n     */\n    protected function resolveView(array $view): View\n    {\n        return $view[1][0] ?? $view[0];\n    }\n}\n"
  },
  {
    "path": "src/LaravelProfiler.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler;\n\nuse JKocik\\Laravel\\Profiler\\Events\\Tracking;\nuse JKocik\\Laravel\\Profiler\\Contracts\\Timer;\nuse JKocik\\Laravel\\Profiler\\Contracts\\Memory;\nuse JKocik\\Laravel\\Profiler\\Events\\Terminating;\nuse JKocik\\Laravel\\Profiler\\Events\\ProfilerBound;\nuse Illuminate\\Foundation\\Bootstrap\\BootProviders;\nuse JKocik\\Laravel\\Profiler\\Contracts\\DataTracker;\nuse JKocik\\Laravel\\Profiler\\Contracts\\DataProcessor;\nuse JKocik\\Laravel\\Profiler\\Contracts\\ExecutionData;\nuse JKocik\\Laravel\\Profiler\\Contracts\\ExecutionWatcher;\nuse JKocik\\Laravel\\Profiler\\Services\\Performance\\TimerService;\nuse JKocik\\Laravel\\Profiler\\Services\\Performance\\MemoryService;\nuse JKocik\\Laravel\\Profiler\\LaravelExecution\\LaravelExecutionData;\n\nclass LaravelProfiler extends BaseProfiler\n{\n    /**\n     * @var DataTracker\n     */\n    protected $dataTracker;\n\n    /**\n     * @return void\n     */\n    protected function boot(): void\n    {\n        $this->bind();\n\n        $this->track();\n\n        $this->listenForTerminating();\n    }\n\n    /**\n     * @return void\n     */\n    protected function bind(): void\n    {\n        $this->app->bind(DataTracker::class, LaravelDataTracker::class);\n\n        $this->app->bind(DataProcessor::class, LaravelDataProcessor::class);\n\n        $this->app->bind(ExecutionWatcher::class, LaravelExecutionWatcher::class);\n\n        $this->app->singleton(ExecutionData::class, function ($app) {\n            return $app->make(LaravelExecutionData::class);\n        });\n\n        $this->app->singleton(Timer::class, function ($app) {\n            return $app->make(TimerService::class);\n        });\n\n        $this->app->singleton(Memory::class, function ($app) {\n            return $app->make(MemoryService::class);\n        });\n\n        event(new ProfilerBound());\n    }\n\n    /**\n     * @return void\n     */\n    protected function track(): void\n    {\n        $this->app->make(ExecutionWatcher::class)->watch();\n\n        $this->dataTracker = $this->app->make(DataTracker::class);\n        $this->dataTracker->track();\n\n        event(new Tracking());\n    }\n\n    /**\n     * @return void\n     */\n    protected function listenForTerminating(): void\n    {\n        $this->app->afterBootstrapping(BootProviders::class, function () {\n            $this->registerTerminating();\n        });\n    }\n\n    /**\n     * @return void\n     */\n    protected function registerTerminating(): void\n    {\n        $this->app->terminating(function () {\n            event(new Terminating());\n\n            $this->dataTracker->terminate();\n            $this->app->make(DataProcessor::class)->process($this->dataTracker);\n        });\n    }\n}\n"
  },
  {
    "path": "src/Processors/BroadcastingProcessor.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Processors;\n\nuse GuzzleHttp\\Client;\nuse GuzzleHttp\\Psr7\\Response;\nuse JKocik\\Laravel\\Profiler\\Contracts\\Processor;\nuse JKocik\\Laravel\\Profiler\\Contracts\\DataTracker;\nuse JKocik\\Laravel\\Profiler\\Services\\ConfigService;\n\nclass BroadcastingProcessor implements Processor\n{\n    /**\n     * @var Client\n     */\n    protected $client;\n\n    /**\n     * @var ConfigService\n     */\n    protected $configService;\n\n    /**\n     * BroadcastingProcessor constructor.\n     * @param Client $client\n     * @param ConfigService $configService\n     */\n    public function __construct(Client $client, ConfigService $configService)\n    {\n        $this->client = $client;\n        $this->configService = $configService;\n    }\n\n    /**\n     * @param DataTracker $dataTracker\n     * @return void\n     */\n    public function process(DataTracker $dataTracker): void\n    {\n        $this->broadcast(\n            $dataTracker,\n            $this->configService->serverHttpConnectionUrl()\n        );\n    }\n\n    /**\n     * @param DataTracker $dataTracker\n     * @param string $url\n     * @return Response\n     * @throws \\GuzzleHttp\\Exception\\GuzzleException\n     */\n    protected function broadcast(DataTracker $dataTracker, string $url): Response\n    {\n        return $this->client->request('POST', $url, [\n            'json' => [\n                'meta' => $dataTracker->meta()->toArray(),\n                'data' => $dataTracker->data()->toArray(),\n            ],\n        ]);\n    }\n}\n"
  },
  {
    "path": "src/Processors/StatusCommandProcessor.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Processors;\n\nuse GuzzleHttp\\Exception\\ConnectException;\nuse JKocik\\Laravel\\Profiler\\Contracts\\DataTracker;\nuse JKocik\\Laravel\\Profiler\\Events\\ProfilerServerConnectionFailed;\nuse JKocik\\Laravel\\Profiler\\Events\\ProfilerServerConnectionSuccessful;\n\nclass StatusCommandProcessor extends BroadcastingProcessor\n{\n    /**\n     * @param DataTracker $dataTracker\n     * @return void\n     */\n    public function process(DataTracker $dataTracker): void\n    {\n        try {\n            $response = $this->broadcast(\n                $dataTracker,\n                $this->configService->serverHttpConnectionUrl() . '/status'\n            );\n\n            $body = json_decode($response->getBody());\n\n            event(new ProfilerServerConnectionSuccessful($body->sockets, $body->clients));\n        } catch (ConnectException $e) {\n            event(new ProfilerServerConnectionFailed());\n            throw $e;\n        }\n    }\n}\n"
  },
  {
    "path": "src/ProfilerResolver.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler;\n\nuse Illuminate\\Foundation\\Application;\nuse JKocik\\Laravel\\Profiler\\Contracts\\Profiler;\nuse JKocik\\Laravel\\Profiler\\Services\\ConfigService;\n\nclass ProfilerResolver\n{\n    /**\n     * @var Application\n     */\n    protected $app;\n\n    /**\n     * @var ConfigService\n     */\n    protected $configService;\n\n    /**\n     * ProfilerResolver constructor.\n     * @param Application $app\n     * @param ConfigService $configService\n     */\n    public function __construct(Application $app, ConfigService $configService)\n    {\n        $this->app = $app;\n        $this->configService = $configService;\n    }\n\n    /**\n     * @return Profiler\n     */\n    public function resolve(): Profiler\n    {\n        if (! $this->configService->isProfilerEnabled()) {\n            return $this->app->make(DisabledProfiler::class);\n        }\n\n        return $this->app->make(LaravelProfiler::class);\n    }\n}\n"
  },
  {
    "path": "src/ServiceProvider.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler;\n\nuse JKocik\\Laravel\\Profiler\\Contracts\\Profiler;\nuse Illuminate\\Support\\ServiceProvider as BaseServiceProvider;\n\nclass ServiceProvider extends BaseServiceProvider\n{\n    /**\n     * @return void\n     */\n    public function register(): void\n    {\n        $this->mergeConfigFrom(static::profilerConfigPath(), 'profiler');\n\n        $this->app->singleton(Profiler::class, function ($app) {\n            return $app->make(ProfilerResolver::class)->resolve();\n        });\n\n        $this->app->make(Profiler::class)->listenForBoot();\n    }\n\n    /**\n     * @return void\n     */\n    public function boot(): void\n    {\n        $this->allowConfigFileToBePublished();\n    }\n\n    /**\n     * @return void\n     */\n    public function allowConfigFileToBePublished(): void\n    {\n        $this->publishes([\n            static::profilerConfigPath() => config_path('profiler.php'),\n        ]);\n    }\n\n    /**\n     * @return string\n     */\n    public static function profilerConfigPath(): string\n    {\n        return __DIR__ . '/../config/profiler.php';\n    }\n}\n"
  },
  {
    "path": "src/Services/ConfigService.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Services;\n\nuse Illuminate\\Config\\Repository;\nuse Illuminate\\Support\\Collection;\nuse Illuminate\\Foundation\\Application;\n\nclass ConfigService\n{\n    /**\n     * @var Application\n     */\n    protected $app;\n\n    /**\n     * @var Repository\n     */\n    protected $config;\n\n    /**\n     * ConfigService constructor.\n     * @param Application $app\n     * @param Repository $config\n     */\n    public function __construct(Application $app, Repository $config)\n    {\n        $this->app = $app;\n        $this->config = $config;\n    }\n\n    /**\n     * @return bool\n     */\n    public function isProfilerEnabled(): bool\n    {\n        $enabledOverrides = Collection::make($this->config->get('profiler.enabled_overrides'));\n        $envToDisable = $enabledOverrides->filter(function ($enabled) {\n            return ! $enabled;\n        })->keys();\n\n        if ($this->app->environment($envToDisable->toArray())) {\n            return false;\n        }\n\n        return $this->config->get('profiler.enabled') === true;\n    }\n\n    /**\n     * @return Collection\n     */\n    public function trackers(): Collection\n    {\n        return Collection::make($this->config->get('profiler.trackers'));\n    }\n\n    /**\n     * @return Collection\n     */\n    public function processors(): Collection\n    {\n        return Collection::make($this->config->get('profiler.processors'));\n    }\n\n    /**\n     * @param array $processors\n     */\n    public function overrideProcessors(array $processors): void\n    {\n        $this->config->set('profiler.processors', $processors);\n    }\n\n    /**\n     * @return Collection\n     */\n    public function pathsToTurnOffProcessors(): Collection\n    {\n        return Collection::make($this->config->get('profiler.turn_off_processors_for_paths'));\n    }\n\n    /**\n     * @return string\n     */\n    public function serverHttpConnectionUrl(): string\n    {\n        $address = $this->config->get('profiler.server_http.address');\n        $port = $this->config->get('profiler.server_http.port');\n\n        return  $address . ':' . $port;\n    }\n\n    /**\n     * @return string\n     */\n    public function serverHttpPort(): string\n    {\n        return $this->config->get('profiler.server_http.port');\n    }\n\n    /**\n     * @return string\n     */\n    public function serverSocketsPort(): string\n    {\n        return $this->config->get('profiler.server_sockets.port');\n    }\n\n    /**\n     * @return bool\n     */\n    public function isViewsDataEnabled(): bool\n    {\n        return $this->config->get('profiler.data.views');\n    }\n\n    /**\n     * @return bool\n     */\n    public function isEventsDataEnabled(): bool\n    {\n        return $this->config->get('profiler.data.events');\n    }\n\n    /**\n     * @return bool\n     */\n    public function isEventsGroupEnabled(): bool\n    {\n        return $this->config->get('profiler.group.events');\n    }\n\n    /**\n     * @param int $level\n     * @return bool\n     */\n    public function handleExceptions(int $level): bool\n    {\n        return $this->config->get('profiler.handle_exceptions') === $level;\n    }\n}\n"
  },
  {
    "path": "src/Services/ConsoleService.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Services;\n\nuse Illuminate\\Foundation\\Application;\n\nclass ConsoleService\n{\n    /**\n     * @var Application\n     */\n    protected $app;\n\n    /**\n     * @var ConfigService\n     */\n    protected $configService;\n\n    /**\n     * ConsoleService constructor.\n     * @param Application $app\n     * @param ConfigService $configService\n     */\n    public function __construct(Application $app, ConfigService $configService)\n    {\n        $this->app = $app;\n        $this->configService = $configService;\n    }\n\n    /**\n     * @return string\n     */\n    public function envInfo(): string\n    {\n        return \"Your current environment is: {$this->app->environment()}\";\n    }\n\n    /**\n     * @return string\n     */\n    public function profilerStatusInfo(): string\n    {\n        $status = $this->configService->isProfilerEnabled() ? 'enabled' : 'disabled';\n\n        return \"Laravel Profiler is: {$status}\";\n    }\n\n    /**\n     * @return string\n     */\n    public function trackersStatusInfo(): string\n    {\n        return \"You have {$this->configService->trackers()->count()} tracker(s) turned on\";\n    }\n\n    /**\n     * @return string\n     */\n    public function trackersCommentLine1(): string\n    {\n        return 'There are 14 trackers available out of the box';\n    }\n\n    /**\n     * @return string\n     */\n    public function trackersCommentLine2(): string\n    {\n        return 'turn them on and off in profiler.php configuration file';\n    }\n\n    /**\n     * @return string\n     */\n    public function connectionStatusInfo(): string\n    {\n        return \"Trying to connect to Profiler Server on {$this->configService->serverHttpConnectionUrl()} ...\";\n    }\n\n    /**\n     * @return string\n     */\n    public function connectionSuccessfulInfo(): string\n    {\n        return 'Connected successfully';\n    }\n\n    /**\n     * @param int $socketsPort\n     * @return string\n     */\n    public function connectionSuccessfulSocketsInfo(int $socketsPort): string\n    {\n        return \"Profiler Server sockets listening on port: {$socketsPort}\";\n    }\n\n    /**\n     * @param int $countClients\n     * @return string\n     */\n    public function connectionSuccessfulClientsInfo(int $countClients): string\n    {\n        return \"You have {$countClients} Profiler Client(s) connected at the moment\";\n    }\n\n    /**\n     * @return string\n     */\n    public function connectionFailedInfo(): string\n    {\n        return 'Connection failed';\n    }\n\n    /**\n     * @return string\n     */\n    public function connectionStatusUnknownInfo(): string\n    {\n        return 'BroadcastingProcessor did not report connection status, connection status is unknown';\n    }\n\n    /**\n     * @return string\n     */\n    public function profilerServerCmd(): string\n    {\n        $http = $this->configService->serverHttpPort();\n        $ws = $this->configService->serverSocketsPort();\n\n        return \"node node_modules/laravel-profiler-client/server/server.js http={$http} ws={$ws}\";\n    }\n\n    /**\n     * @param bool $manual\n     * @return string\n     */\n    public function profilerClientCmd(bool $manual): string\n    {\n        $options = $manual ? '' : ' -o -s';\n\n        return \"node_modules/.bin/http-server node_modules/laravel-profiler-client/dist/{$options}\";\n    }\n}\n"
  },
  {
    "path": "src/Services/GeneratorService.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Services;\n\nclass GeneratorService\n{\n    /**\n     * @return string\n     */\n    public function unique32CharsId(): string\n    {\n        return md5(uniqid('', true));\n    }\n}\n"
  },
  {
    "path": "src/Services/LogService.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Services;\n\nuse Exception;\nuse Illuminate\\Support\\Facades\\Log;\n\nclass LogService\n{\n    const HANDLE_EXCEPTIONS_LOG = 1;\n    const HANDLE_EXCEPTIONS_THROW = 666;\n\n    /**\n     * @var ConfigService\n     */\n    protected $configService;\n\n    /**\n     * LogService constructor.\n     * @param ConfigService $configService\n     */\n    public function __construct(ConfigService $configService)\n    {\n        $this->configService = $configService;\n    }\n\n    /**\n     * @param Exception $e\n     * @throws Exception\n     * @return void\n     */\n    public function error(Exception $e): void\n    {\n        if ($this->configService->handleExceptions(self::HANDLE_EXCEPTIONS_THROW)) {\n            throw $e;\n        }\n\n        if ($this->configService->handleExceptions(self::HANDLE_EXCEPTIONS_LOG)) {\n            Log::error($e);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Services/ParamsService.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Services;\n\nuse Illuminate\\Support\\Collection;\n\nclass ParamsService\n{\n    /**\n     * @param $param\n     * @return mixed\n     */\n    public function resolve($param)\n    {\n        if (is_object($param)) {\n            return $this->resolveObject($param);\n        }\n\n        if (is_array($param)) {\n            return array_map(function ($item) {\n                return $this->resolve($item);\n            }, $param);\n        }\n\n        return $param;\n    }\n\n    /**\n     * @param array $params\n     * @return array\n     */\n    public function resolveFlattenFromArray(array $params): array\n    {\n        return array_map(function ($param) {\n            return $this->resolveFlatten($param);\n        }, $params);\n    }\n\n    /**\n     * @param $param\n     * @return string\n     */\n    protected function resolveFlatten($param): string\n    {\n        if ($param instanceof Collection) {\n            return get_class($param) . ': ' . $param->count() . ' item(s)';\n        }\n\n        if (is_object($param)) {\n            return get_class($param);\n        }\n\n        if (is_array($param)) {\n            return 'array: ' . count($param) . ' item(s)';\n        }\n\n        return gettype($param);\n    }\n\n    /**\n     * @param $param\n     * @return array|string\n     */\n    protected function resolveObject($param)\n    {\n        if (method_exists($param, 'toArray')) {\n            return $this->resolve($param->toArray());\n        }\n\n        return get_class($param);\n    }\n}\n"
  },
  {
    "path": "src/Services/Performance/MemoryService.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Services\\Performance;\n\nuse Illuminate\\Support\\Collection;\nuse Illuminate\\Foundation\\Application;\nuse JKocik\\Laravel\\Profiler\\Contracts\\Memory;\n\nclass MemoryService implements Memory\n{\n    /**\n     * @var Application\n     */\n    protected $app;\n\n    /**\n     * @var Collection\n     */\n    protected $memory;\n\n    /**\n     * MemoryService constructor.\n     * @param Application $app\n     */\n    public function __construct(Application $app)\n    {\n        $this->app = $app;\n        $this->memory = Collection::make();\n    }\n\n    /**\n     * @return void\n     */\n    public function recordPeak(): void\n    {\n        $this->memory->put('peak', memory_get_peak_usage());\n    }\n\n    /**\n     * @return Collection\n     */\n    public function all(): Collection\n    {\n        return $this->memory;\n    }\n}\n"
  },
  {
    "path": "src/Services/Performance/NullTimerService.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Services\\Performance;\n\nuse JKocik\\Laravel\\Profiler\\Contracts\\Timer;\n\nclass NullTimerService implements Timer\n{\n    /**\n     * @param string $name\n     * @return void\n     */\n    public function startCustom(string $name): void\n    {\n\n    }\n\n    /**\n     * @param string $name\n     * @return void\n     */\n    public function finishCustom(string $name): void\n    {\n\n    }\n\n    /**\n     * @param string $name\n     * @return float\n     */\n    public function millisecondsCustom(string $name): float\n    {\n        return -1;\n    }\n}\n"
  },
  {
    "path": "src/Services/Performance/TimerException.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Services\\Performance;\n\nuse Exception;\n\nclass TimerException extends Exception\n{\n\n}\n"
  },
  {
    "path": "src/Services/Performance/TimerService.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Services\\Performance;\n\nuse Illuminate\\Support\\Collection;\nuse Illuminate\\Foundation\\Application;\nuse JKocik\\Laravel\\Profiler\\Contracts\\Timer;\n\nclass TimerService implements Timer\n{\n    /**\n     * @var Application\n     */\n    protected $app;\n\n    /**\n     * @var Collection\n     */\n    protected $time;\n\n    /**\n     * @var string\n     */\n    protected $customNamePrefix = 'custom-';\n\n    /**\n     * TimerService constructor.\n     * @param Application $app\n     */\n    public function __construct(Application $app)\n    {\n        $this->app = $app;\n        $this->time = Collection::make();\n    }\n\n    /**\n     * @param string $name\n     * @return void\n     */\n    public function start(string $name): void\n    {\n        $this->time->put($name, [\n            'start' => $this->now(),\n        ]);\n    }\n\n    /**\n     * @param string $name\n     * @return void\n     */\n    public function finish(string $name): void\n    {\n        $this->time->put($name, array_merge($this->getByName($name), [\n            'finish' => $this->now(),\n        ]));\n    }\n\n    /**\n     * @param string $name\n     * @return void\n     * @throws TimerException\n     */\n    public function startCustom(string $name): void\n    {\n        $customName = $this->customNamePrefix . $name;\n\n        $this->guardTimerAlreadyStarted($customName);\n\n        $this->start($customName);\n    }\n\n    /**\n     * @param string $name\n     * @return void\n     * @throws TimerException\n     */\n    public function finishCustom(string $name): void\n    {\n        $customName = $this->customNamePrefix . $name;\n\n        $this->guardTimerAlreadyFinished($customName);\n\n        $this->guardTimerNotStartedYet($customName);\n\n        $this->finish($customName);\n    }\n\n    /**\n     * @return void\n     */\n    public function startLaravel(): void\n    {\n        $this->time->put('laravel', [\n            'start' => $this->laravelStartTimeOrNow(),\n        ]);\n    }\n\n    /**\n     * @return void\n     */\n    public function finishLaravel(): void\n    {\n        $this->finish('laravel');\n    }\n\n    /**\n     * @param string $name\n     * @return float\n     */\n    public function milliseconds(string $name): float\n    {\n        return $this->millisecondsOf(\n            $this->getByName($name)\n        );\n    }\n\n    /**\n     * @param string $name\n     * @return float\n     */\n    public function millisecondsCustom(string $name): float\n    {\n        return $this->milliseconds($this->customNamePrefix . $name);\n    }\n\n    /**\n     * @return array\n     */\n    public function all(): array\n    {\n        return $this->time->filter(function ($item) {\n            return $this->isCompleted($item);\n        })->map(function ($item) {\n            return $this->millisecondsOf($item);\n        })->toArray();\n    }\n\n    /**\n     * @return float\n     */\n    protected function now(): float\n    {\n        return \\microtime(true);\n    }\n\n    /**\n     * @return float\n     */\n    protected function laravelStartTimeOrNow(): float\n    {\n        return defined('LARAVEL_START') && ! $this->app->environment('testing')\n            ? LARAVEL_START\n            : $this->now();\n    }\n\n    /**\n     * @param string $name\n     * @return array\n     */\n    protected function getByName(string $name): array\n    {\n        return $this->time->first(function ($a, $b) use ($name) {\n            return $a === $name || $b === $name;\n        }) ?? [];\n    }\n\n    /**\n     * @param array $item\n     * @return float\n     */\n    protected function millisecondsOf(array $item): float\n    {\n        if (! $this->isCompleted($item)) {\n            return -1;\n        }\n\n        return ($item['finish'] - $item['start']) * 1000;\n    }\n\n    /**\n     * @param array $item\n     * @return bool\n     */\n    protected function isCompleted(array $item): bool\n    {\n        return isset($item['start']) && isset($item['finish']);\n    }\n\n    /**\n     * @param string $name\n     * @return void\n     * @throws TimerException\n     */\n    protected function guardTimerAlreadyStarted(string $name): void\n    {\n        if ($this->time->has($name)) {\n            throw new TimerException(\"Laravel Profiler custom time tracker for {$name} already exists and can not be started twice\");\n        }\n    }\n\n    /**\n     * @param string $name\n     * @return void\n     * @throws TimerException\n     */\n    protected function guardTimerAlreadyFinished(string $name): void\n    {\n        if ($this->isCompleted($this->getByName($name))) {\n            throw new TimerException(\"Laravel Profiler custom time tracker for {$name} already exists and can not be finished twice\");\n        }\n    }\n\n    /**\n     * @param string $name\n     * @return void\n     * @throws TimerException\n     */\n    protected function guardTimerNotStartedYet(string $name): void\n    {\n        if (! $this->time->has($name)) {\n            throw new TimerException(\"Laravel Profiler custom time tracker for {$name} is not started yet\");\n        }\n    }\n}\n"
  },
  {
    "path": "src/Services/helpers.php",
    "content": "<?php\n\nuse JKocik\\Laravel\\Profiler\\Contracts\\Timer;\nuse JKocik\\Laravel\\Profiler\\Contracts\\Profiler;\nuse JKocik\\Laravel\\Profiler\\Services\\LogService;\nuse JKocik\\Laravel\\Profiler\\Services\\Performance\\TimerException;\n\nif (! function_exists('profiler_start')) {\n    function profiler_start(string $name): void\n    {\n        try {\n            app()->make(Timer::class)->startCustom($name);\n        } catch (TimerException $e) {\n            app()->make(LogService::class)->error($e);\n        }\n    }\n}\n\nif (! function_exists('profiler_finish')) {\n    function profiler_finish(string $name): void\n    {\n        try {\n            app()->make(Timer::class)->finishCustom($name);\n        } catch (TimerException $e) {\n            app()->make(LogService::class)->error($e);\n        }\n    }\n}\n\nif (! function_exists('profiler_reset')) {\n    function profiler_reset(): void\n    {\n        app()->make(Profiler::class)->resetTrackers();\n    }\n}\n"
  },
  {
    "path": "src/Trackers/ApplicationTracker.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Trackers;\n\nuse Illuminate\\Support\\Collection;\nuse Illuminate\\Foundation\\Application;\nuse JKocik\\Laravel\\Profiler\\Services\\GeneratorService;\n\nclass ApplicationTracker extends BaseTracker\n{\n    /**\n     * @var GeneratorService\n     */\n    protected $generatorService;\n\n    /**\n     * ApplicationTracker constructor.\n     * @param Application $app\n     * @param GeneratorService $generatorService\n     */\n    public function __construct(Application $app, GeneratorService $generatorService)\n    {\n        parent::__construct($app);\n\n        $this->generatorService = $generatorService;\n    }\n\n    /**\n     * @return void\n     */\n    public function terminate(): void\n    {\n        $this->meta->put('execution_at', time());\n        $this->meta->put('id', $this->generatorService->unique32CharsId());\n        $this->meta->put('laravel_version', $this->app->version());\n        $this->meta->put('php_version', phpversion());\n        $this->meta->put('env', $this->app->environment());\n        $this->meta->put('is_running_in_console', $this->app->runningInConsole());\n\n        $this->data->put('application', Collection::make([\n            'locale' => $this->app->getLocale(),\n            'configuration_is_cached' => $this->app->configurationIsCached(),\n            'routes_are_cached' => $this->app->routesAreCached(),\n            'is_down_for_maintenance' => $this->app->isDownForMaintenance(),\n            'should_skip_middleware' => $this->app->shouldSkipMiddleware(),\n        ]));\n    }\n}\n"
  },
  {
    "path": "src/Trackers/AuthTracker.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Trackers;\n\nuse Illuminate\\Foundation\\Application;\nuse JKocik\\Laravel\\Profiler\\LaravelListeners\\AuthListener;\n\nclass AuthTracker extends BaseTracker\n{\n    /**\n     * @var AuthListener\n     */\n    protected $authListener;\n\n    /**\n     * AuthTracker constructor.\n     * @param Application $app\n     * @param AuthListener $authListener\n     */\n    public function __construct(Application $app, AuthListener $authListener)\n    {\n        parent::__construct($app);\n\n        $this->authListener = $authListener;\n        $this->authListener->listen();\n    }\n\n    /**\n     * @return void\n     */\n    public function terminate(): void\n    {\n        $this->data->put('auth', $this->authListener->user());\n    }\n}\n"
  },
  {
    "path": "src/Trackers/BaseTracker.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Trackers;\n\nuse Illuminate\\Support\\Collection;\nuse Illuminate\\Foundation\\Application;\nuse JKocik\\Laravel\\Profiler\\Contracts\\Tracker;\n\nabstract class BaseTracker implements Tracker\n{\n    /**\n     * @var Application\n     */\n    protected $app;\n\n    /**\n     * @var Collection\n     */\n    protected $meta;\n\n    /**\n     * @var Collection\n     */\n    protected $data;\n\n    /**\n     * BaseTracker constructor.\n     * @param Application $app\n     */\n    public function __construct(Application $app)\n    {\n        $this->app = $app;\n        $this->meta = new Collection();\n        $this->data = new Collection();\n    }\n\n    /**\n     * @return Collection\n     */\n    public function meta(): Collection\n    {\n        return $this->meta;\n    }\n\n    /**\n     * @return Collection\n     */\n    public function data(): Collection\n    {\n        return $this->data;\n    }\n}\n"
  },
  {
    "path": "src/Trackers/BindingsTracker.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Trackers;\n\nuse Illuminate\\Support\\Collection;\nuse Illuminate\\Contracts\\Container\\BindingResolutionException;\n\nclass BindingsTracker extends BaseTracker\n{\n    /**\n     * @return void\n     */\n    public function terminate(): void\n    {\n        $bindings = $this->abstracts()->map(function ($abstract) {\n            try {\n                $resolved = $this->resolved($abstract);\n            } catch (BindingResolutionException $e) {}\n\n            return [\n                'abstract' => $abstract,\n                'resolved' => $resolved ?? null,\n            ];\n        });\n\n        $this->data->put('bindings', $bindings);\n    }\n\n    /**\n     * @return Collection\n     */\n    protected function abstracts(): Collection\n    {\n        return Collection::make(\n            array_keys($this->app->getBindings())\n        );\n    }\n\n    /**\n     * @param string $abstract\n     * @return string\n     * @throws BindingResolutionException\n     */\n    protected function resolved(string $abstract): string\n    {\n        if (! $this->app->resolved($abstract)) {\n            throw new BindingResolutionException();\n        }\n\n        $concrete = $this->app->make($abstract);\n\n        if (is_object($concrete)) {\n            return get_class($concrete);\n        }\n\n        return gettype($concrete);\n    }\n}\n"
  },
  {
    "path": "src/Trackers/ConfigTracker.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Trackers;\n\nuse Illuminate\\Support\\Collection;\n\nclass ConfigTracker extends BaseTracker\n{\n    /**\n     * @return void\n     */\n    public function terminate(): void\n    {\n        $this->data->put('config', $this->config());\n    }\n\n    /**\n     * @return Collection\n     */\n    protected function config(): Collection\n    {\n        return Collection::make(\n            $this->hideSecretValues(\n                $this->app->make('config')->all()\n            )\n        );\n    }\n\n    /**\n     * @param array $config\n     * @return array\n     */\n    protected function hideSecretValues(array $config): array\n    {\n        $keys = array_keys($config);\n\n        return array_map(function ($value) use (&$keys) {\n            $key = array_shift($keys);\n\n            if (is_array($value)) {\n                return $this->hideSecretValues($value);\n            }\n\n            if (is_string($value) && preg_match('/^(password|key|secret)$/i', $key)) {\n                $value = str_repeat('*', strlen($value));\n            }\n\n            return $value;\n        }, $config);\n    }\n}\n"
  },
  {
    "path": "src/Trackers/ContentTracker.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Trackers;\n\nuse Illuminate\\Foundation\\Application;\nuse JKocik\\Laravel\\Profiler\\Contracts\\ExecutionData;\n\nclass ContentTracker extends BaseTracker\n{\n    /**\n     * @var ExecutionData\n     */\n    protected $executionData;\n\n    /**\n     * ContentTracker constructor.\n     * @param Application $app\n     * @param ExecutionData $executionData\n     */\n    public function __construct(Application $app, ExecutionData $executionData)\n    {\n        parent::__construct($app);\n\n        $this->executionData = $executionData;\n    }\n\n    /**\n     * @return void\n     */\n    public function terminate(): void\n    {\n        $content = $this->executionData->content();\n\n        $this->meta = $content->meta();\n        $this->data->put('content', $content->data()->get('content'));\n    }\n}\n"
  },
  {
    "path": "src/Trackers/EventsTracker.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Trackers;\n\nuse Illuminate\\Support\\Collection;\nuse Illuminate\\Foundation\\Application;\nuse JKocik\\Laravel\\Profiler\\Services\\ConfigService;\nuse JKocik\\Laravel\\Profiler\\Services\\ParamsService;\nuse JKocik\\Laravel\\Profiler\\LaravelListeners\\EventsListener;\n\nclass EventsTracker extends BaseTracker\n{\n    /**\n     * @var ParamsService\n     */\n    protected $paramsService;\n\n    /**\n     * @var ConfigService\n     */\n    protected $configService;\n\n    /**\n     * @var EventsListener\n     */\n    protected $eventsListener;\n\n    /**\n     * EventsTracker constructor.\n     * @param Application $app\n     * @param ParamsService $paramsService\n     * @param ConfigService $configService\n     * @param EventsListener $eventsListener\n     */\n    public function __construct(\n        Application $app,\n        ParamsService $paramsService,\n        ConfigService $configService,\n        EventsListener $eventsListener\n    ) {\n        parent::__construct($app);\n\n        $this->paramsService = $paramsService;\n        $this->configService = $configService;\n        $this->eventsListener = $eventsListener;\n        $this->eventsListener->listen();\n    }\n\n    /**\n     * @return void\n     */\n    public function terminate(): void\n    {\n        $events = $this->eventsListener->events()->map(function ($item) {\n            list($event, $payload, $name, $count) = $item;\n\n            if ($this->shouldTrackData($count)) {\n                return [\n                    'name' => $name,\n                    'count' => $count,\n                    'data' => $this->resolveData($event, $payload),\n                ];\n            }\n\n            return [\n                'name' => $name,\n                'count' => $count,\n            ];\n        });\n\n        $this->meta->put('events_count', $this->eventsListener->count());\n        $this->data->put('events', $events);\n    }\n\n    /**\n     * @param int $count\n     * @return bool\n     */\n    protected function shouldTrackData(int $count): bool\n    {\n        return $this->configService->isEventsDataEnabled() && $count == 1;\n    }\n\n    /**\n     * @param $event\n     * @param $payload\n     * @return Collection\n     */\n    protected function resolveData($event, $payload): Collection\n    {\n        $event = is_array($payload) ? $payload[0] : $event;\n\n        $class = new \\ReflectionClass($event);\n\n        $publicProps = Collection::make(\n            $class->getProperties(\\ReflectionProperty::IS_PUBLIC)\n        );\n\n        if (method_exists($publicProps, 'mapWithKeys')) {\n            return $this->propsMapWithKeys($publicProps, $event);\n        }\n\n        return $this->propsMap($publicProps, $event); // @codeCoverageIgnore\n    }\n\n    /**\n     * @param Collection $publicProps\n     * @param $event\n     * @return Collection\n     */\n    protected function propsMapWithKeys(Collection $publicProps, $event): Collection\n    {\n        return $publicProps->mapWithKeys(function ($prop) use ($event) {\n            return [\n                $prop->name => $this->paramsService->resolve($event->{$prop->name}),\n            ];\n        });\n    }\n\n    /**\n     * @codeCoverageIgnore\n     *\n     * @param Collection $publicProps\n     * @param $event\n     * @return Collection\n     */\n    protected function propsMap(Collection $publicProps, $event): Collection\n    {\n        return $publicProps->map(function ($prop) use ($event) {\n            return [\n                $prop->name => $this->paramsService->resolve($event->{$prop->name}),\n            ];\n        })->flatten(1);\n    }\n}\n"
  },
  {
    "path": "src/Trackers/ExceptionTracker.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Trackers;\n\nuse Illuminate\\Support\\Arr;\nuse Illuminate\\Support\\Collection;\nuse Illuminate\\Foundation\\Application;\nuse JKocik\\Laravel\\Profiler\\LaravelListeners\\ExceptionListener;\nuse JKocik\\Laravel\\Profiler\\LaravelExecution\\ExceptionHandlerTillVersion6;\nuse JKocik\\Laravel\\Profiler\\LaravelExecution\\ExceptionHandlerFromVersion7;\n\nclass ExceptionTracker extends BaseTracker\n{\n    /**\n     * @var ExceptionListener\n     */\n    protected $exceptionListener;\n\n    /**\n     * ExceptionTracker constructor.\n     * @param Application $app\n     * @param ExceptionListener $exceptionListener\n     */\n    public function __construct(Application $app, ExceptionListener $exceptionListener)\n    {\n        parent::__construct($app);\n\n        $this->exceptionListener = $exceptionListener;\n        $this->exceptionListener->listen();\n\n        $this->bindExceptionHandler($app);\n    }\n\n    /**\n     * @param Application $app\n     * @return void\n     */\n    protected function bindExceptionHandler(Application $app): void\n    {\n        $version = (int) $app->version();\n\n        $handler = $version < 7\n            ? ExceptionHandlerTillVersion6::class\n            : ExceptionHandlerFromVersion7::class; // @codeCoverageIgnore\n\n        $app->singleton(\\App\\Exceptions\\Handler::class, $handler);\n    }\n\n    /**\n     * @return void\n     */\n    public function terminate(): void\n    {\n        $exception = $this->exceptionListener->exception() ? $this->exception() : null;\n\n        $this->data->put('exception', $exception);\n    }\n\n    /**\n     * @return Collection\n     */\n    protected function exception(): Collection\n    {\n        $exception = $this->exceptionListener->exception();\n\n        return Collection::make([\n            'message' => $exception->getMessage(),\n            'exception' => get_class($exception),\n            'file' => $exception->getFile(),\n            'line' => $exception->getLine(),\n            'trace' => Collection::make($exception->getTrace())->map(function ($trace) {\n                return Arr::except($trace, ['args', 'type']);\n            }),\n        ]);\n    }\n}\n"
  },
  {
    "path": "src/Trackers/PathsTracker.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Trackers;\n\nuse Illuminate\\Support\\Collection;\n\nclass PathsTracker extends BaseTracker\n{\n    /**\n     * @return void\n     */\n    public function terminate(): void\n    {\n        $paths = $this->paths()->map(function ($path, $name) {\n            return [\n                'name' => $name,\n                'path' => $path,\n            ];\n        })->values();\n\n        $this->data->put('paths', $paths);\n    }\n\n    /**\n     * @return Collection\n     */\n    protected function paths(): Collection\n    {\n        return Collection::make([\n            'app_path' => $this->app->path(),\n            'base_path' => $this->app->basePath(),\n            'lang_path' => $this->app->langPath(),\n            'config_path' => $this->app->configPath(),\n            'public_path' => $this->app->publicPath(),\n            'storage_path' => $this->app->storagePath(),\n            'resource_path' => $this->resourcePath(),\n            'database_path' => $this->app->databasePath(),\n            'bootstrap_path' => $this->app->bootstrapPath(),\n            'cached_config_path' => $this->app->getCachedConfigPath(),\n            'cached_routes_path' => $this->app->getCachedRoutesPath(),\n            'cached_services_path' => $this->app->getCachedServicesPath(),\n            'cached_packages_path' => $this->getCachedPackagesPath(),\n            'environment_file_path' => $this->app->environmentFilePath(),\n        ])->filter(function ($item) {\n            return !! $item;\n        });\n    }\n\n    /**\n     * @return string\n     */\n    protected function resourcePath(): string\n    {\n        return method_exists($this->app, 'resourcePath')\n            ? $this->app->resourcePath()\n            : '';\n    }\n\n    /**\n     * @return string\n     */\n    protected function getCachedPackagesPath(): string\n    {\n        return method_exists($this->app, 'getCachedPackagesPath')\n            ? $this->app->getCachedPackagesPath()\n            : '';\n    }\n}\n"
  },
  {
    "path": "src/Trackers/PerformanceTracker.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Trackers;\n\nuse Illuminate\\Support\\Collection;\nuse Illuminate\\Foundation\\Application;\nuse JKocik\\Laravel\\Profiler\\Contracts\\Timer;\nuse JKocik\\Laravel\\Profiler\\Contracts\\Memory;\nuse JKocik\\Laravel\\Profiler\\LaravelListeners\\PerformanceListener;\n\nclass PerformanceTracker extends BaseTracker\n{\n    /**\n     * @var Timer\n     */\n    protected $timer;\n\n    /**\n     * @var Memory\n     */\n    protected $memory;\n\n    /**\n     * PerformanceTracker constructor.\n     * @param Application $app\n     * @param Timer $timer\n     * @param Memory $memory\n     * @param PerformanceListener $performanceListener\n     */\n    public function __construct(\n        Application $app,\n        Timer $timer,\n        Memory $memory,\n        PerformanceListener $performanceListener\n    ) {\n        parent::__construct($app);\n\n        $this->timer = $timer;\n        $this->memory = $memory;\n        $performanceListener->listen();\n    }\n\n    /**\n     * @return void\n     */\n    public function terminate(): void\n    {\n        $this->data->put('performance', Collection::make([\n            'timer' => $this->timer->all(),\n            'memory' => $this->memory->all(),\n        ]));\n    }\n}\n"
  },
  {
    "path": "src/Trackers/QueriesTracker.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Trackers;\n\nuse Illuminate\\Foundation\\Application;\nuse JKocik\\Laravel\\Profiler\\LaravelListeners\\QueriesListener;\n\nclass QueriesTracker extends BaseTracker\n{\n    /**\n     * @var QueriesListener\n     */\n    protected $queriesListener;\n\n    /**\n     * QueriesTracker constructor.\n     * @param Application $app\n     * @param QueriesListener $queriesListener\n     */\n    public function __construct(Application $app, QueriesListener $queriesListener)\n    {\n        parent::__construct($app);\n\n        $this->queriesListener = $queriesListener;\n        $this->queriesListener->listen();\n    }\n\n    /**\n     * @return void\n     */\n    public function terminate(): void\n    {\n        $queries = $this->queriesListener->queries()->map(function ($item) {\n            if ($this->isTransactionType($item[0])) {\n                return $this->terminateTransaction($item);\n            }\n\n            return $this->terminateQuery($item);\n        });\n\n        $this->meta->put('queries_count', $this->queriesListener->count());\n        $this->data->put('queries', $queries);\n    }\n\n    /**\n     * @param array $item\n     * @return array\n     */\n    protected function terminateTransaction(array $item): array\n    {\n        list($type, $database, $name) = $item;\n\n        return [\n            'type' => $type,\n            'database' => $database,\n            'name' => $name,\n        ];\n    }\n\n    /**\n     * @param array $item\n     * @return array\n     */\n    protected function terminateQuery(array $item): array\n    {\n        list($type, $sql, $time, $database, $name, $bindings, $bindingsQuoted) = $item;\n\n        $formattedSql = $this->formatSql($sql);\n\n        return [\n            'type' => $type,\n            'sql' => $formattedSql,\n            'bindings' => $bindings,\n            'time' => $time,\n            'database' => $database,\n            'name' => $name,\n            'query' => $this->queryWithBindings($bindingsQuoted, $formattedSql),\n        ];\n    }\n\n    /**\n     * @param string $type\n     * @return bool\n     */\n    protected function isTransactionType(string $type): bool\n    {\n        $transactionTypes = [\n            'transaction-begin',\n            'transaction-commit',\n            'transaction-rollback',\n        ];\n\n        return in_array($type, $transactionTypes);\n    }\n\n    /**\n     * @param string $sql\n     * @return string\n     */\n    protected function formatSql(string $sql): string\n    {\n        return preg_replace('/\"/', '`', $sql);\n    }\n\n    /**\n     * @param array $bindingsQuoted\n     * @param string $formattedSql\n     * @return string\n     */\n    protected function queryWithBindings(array $bindingsQuoted, string $formattedSql): string\n    {\n        foreach ($bindingsQuoted as $key => $binding) {\n            $formattedSql = preg_replace($this->bindingRegex($key), $binding, $formattedSql, 1);\n        }\n\n        return $formattedSql;\n    }\n\n    /**\n     * @param $key\n     * @return string\n     */\n    protected function bindingRegex($key): string\n    {\n        return is_int($key) ? \"/\\?/\" : \"/:{$key}/\";\n    }\n}\n"
  },
  {
    "path": "src/Trackers/RedisTracker.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Trackers;\n\nuse Illuminate\\Foundation\\Application;\nuse JKocik\\Laravel\\Profiler\\LaravelListeners\\RedisListener;\n\nclass RedisTracker extends BaseTracker\n{\n    /**\n     * @var RedisListener\n     */\n    protected $redisListener;\n\n    /**\n     * @var bool\n     */\n    protected $redisCanBeTracked = false;\n\n    /**\n     * RedisTracker constructor.\n     * @param Application $app\n     * @param RedisListener $redisListener\n     */\n    public function __construct(Application $app, RedisListener $redisListener)\n    {\n        parent::__construct($app);\n\n        $this->enableRedisEvents();\n\n        $this->redisListener = $redisListener;\n        $this->redisListener->listen();\n    }\n\n    /**\n     * @return void\n     */\n    public function terminate(): void\n    {\n        $commands = $this->redisListener->commands()->map(function ($item) {\n            return $this->terminateCommands($item);\n        });\n\n        $this->meta->put('redis_count', $this->redisListener->count());\n        $this->meta->put('redis_can_be_tracked', $this->redisCanBeTracked);\n        $this->data->put('redis', $commands);\n    }\n\n    /**\n     * @param array $item\n     * @return array\n     */\n    protected function terminateCommands(array $item): array\n    {\n        list($command, $time, $name, $parameters) = $item;\n\n        return [\n            'command' => $command,\n            'time' => $time,\n            'name' => $name,\n            'parameters' => $parameters,\n        ];\n    }\n\n    /**\n     * @return void\n     */\n    protected function enableRedisEvents(): void\n    {\n        $manager = $this->app->make('redis');\n\n        if (! method_exists($manager, 'enableEvents')) {\n            return; // @codeCoverageIgnore\n        }\n\n        $this->redisCanBeTracked = true;\n        $manager->enableEvents();\n    }\n}\n"
  },
  {
    "path": "src/Trackers/RequestTracker.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Trackers;\n\nuse Illuminate\\Foundation\\Application;\nuse JKocik\\Laravel\\Profiler\\Contracts\\ExecutionData;\n\nclass RequestTracker extends BaseTracker\n{\n    /**\n     * @var ExecutionData\n     */\n    protected $executionData;\n\n    /**\n     * RequestTracker constructor.\n     * @param Application $app\n     * @param ExecutionData $executionData\n     */\n    public function __construct(Application $app, ExecutionData $executionData)\n    {\n        parent::__construct($app);\n\n        $this->executionData = $executionData;\n    }\n\n    /**\n     * @return void\n     */\n    public function terminate(): void\n    {\n        $request = $this->executionData->request();\n\n        $this->meta = $request->meta();\n        $this->data->put('request', $request->data());\n    }\n}\n"
  },
  {
    "path": "src/Trackers/ResponseTracker.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Trackers;\n\nuse Illuminate\\Foundation\\Application;\nuse JKocik\\Laravel\\Profiler\\Contracts\\ExecutionData;\n\nclass ResponseTracker extends BaseTracker\n{\n    /**\n     * @var ExecutionData\n     */\n    protected $executionData;\n\n    /**\n     * RequestTracker constructor.\n     * @param Application $app\n     * @param ExecutionData $executionData\n     */\n    public function __construct(Application $app, ExecutionData $executionData)\n    {\n        parent::__construct($app);\n\n        $this->executionData = $executionData;\n    }\n\n    /**\n     * @return void\n     */\n    public function terminate(): void\n    {\n        $response = $this->executionData->response();\n\n        $this->meta = $response->meta();\n        $this->data->put('response', $response->data());\n    }\n}\n"
  },
  {
    "path": "src/Trackers/RouteTracker.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Trackers;\n\nuse Illuminate\\Foundation\\Application;\nuse JKocik\\Laravel\\Profiler\\Contracts\\ExecutionData;\n\nclass RouteTracker extends BaseTracker\n{\n    /**\n     * @var ExecutionData\n     */\n    protected $executionData;\n\n    /**\n     * RequestTracker constructor.\n     * @param Application $app\n     * @param ExecutionData $executionData\n     */\n    public function __construct(Application $app, ExecutionData $executionData)\n    {\n        parent::__construct($app);\n\n        $this->executionData = $executionData;\n    }\n\n    /**\n     * @return void\n     */\n    public function terminate(): void\n    {\n        $route = $this->executionData->route();\n\n        $this->meta = $route->meta();\n        $this->data->put('route', $route->data());\n    }\n}\n"
  },
  {
    "path": "src/Trackers/ServerTracker.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Trackers;\n\nuse Illuminate\\Foundation\\Application;\nuse JKocik\\Laravel\\Profiler\\Contracts\\ExecutionData;\n\nclass ServerTracker extends BaseTracker\n{\n    /**\n     * @var ExecutionData\n     */\n    protected $executionData;\n\n    /**\n     * ServerTracker constructor.\n     * @param Application $app\n     * @param ExecutionData $executionData\n     */\n    public function __construct(Application $app, ExecutionData $executionData)\n    {\n        parent::__construct($app);\n\n        $this->executionData = $executionData;\n    }\n\n    /**\n     * @return void\n     */\n    public function terminate(): void\n    {\n        $server = $this->executionData->server();\n\n        $this->meta = $server->meta();\n        $this->data->put('server', $server->data());\n    }\n}\n"
  },
  {
    "path": "src/Trackers/ServiceProvidersTracker.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Trackers;\n\nuse Illuminate\\Support\\Collection;\n\nclass ServiceProvidersTracker extends BaseTracker\n{\n    /**\n     * @return void\n     */\n    public function terminate(): void\n    {\n        $this->data->put('service_providers', $this->loadedProviders());\n    }\n\n    /**\n     * @return Collection\n     */\n    protected function loadedProviders(): Collection\n    {\n        return Collection::make(\n            array_keys($this->app->getLoadedProviders())\n        );\n    }\n}\n"
  },
  {
    "path": "src/Trackers/SessionTracker.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Trackers;\n\nuse Illuminate\\Foundation\\Application;\nuse JKocik\\Laravel\\Profiler\\Contracts\\ExecutionData;\n\nclass SessionTracker extends BaseTracker\n{\n    /**\n     * @var ExecutionData\n     */\n    protected $executionData;\n\n    /**\n     * RequestTracker constructor.\n     * @param Application $app\n     * @param ExecutionData $executionData\n     */\n    public function __construct(Application $app, ExecutionData $executionData)\n    {\n        parent::__construct($app);\n\n        $this->executionData = $executionData;\n    }\n\n    /**\n     * @return void\n     */\n    public function terminate(): void\n    {\n        $session = $this->executionData->session();\n\n        $this->meta = $session->meta();\n        $this->data->put('session', $session->data());\n    }\n}\n"
  },
  {
    "path": "src/Trackers/ViewsTracker.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Trackers;\n\nuse Illuminate\\View\\View;\nuse Illuminate\\Foundation\\Application;\nuse JKocik\\Laravel\\Profiler\\Services\\ConfigService;\nuse JKocik\\Laravel\\Profiler\\Services\\ParamsService;\nuse JKocik\\Laravel\\Profiler\\LaravelListeners\\ViewsListener;\n\nclass ViewsTracker extends BaseTracker\n{\n    /**\n     * @var ConfigService\n     */\n    protected $configService;\n\n    /**\n     * @var ParamsService\n     */\n    protected $paramsService;\n\n    /**\n     * @var ViewsListener\n     */\n    protected $viewsListener;\n\n    /**\n     * ViewsTracker constructor.\n     * @param Application $app\n     * @param ConfigService $configService\n     * @param ParamsService $paramsService\n     * @param ViewsListener $viewsListener\n     */\n    public function __construct(\n        Application $app,\n        ConfigService $configService,\n        ParamsService $paramsService,\n        ViewsListener $viewsListener\n    ) {\n        parent::__construct($app);\n\n        $this->configService = $configService;\n        $this->paramsService = $paramsService;\n        $this->viewsListener = $viewsListener;\n        $this->viewsListener->listen();\n    }\n\n    /**\n     * @return void\n     */\n    public function terminate(): void\n    {\n        $views = $this->viewsListener->views()->map(function (View $view) {\n            if ($this->configService->isViewsDataEnabled()) {\n                return [\n                    'name' => $view->name(),\n                    'path' => $view->getPath(),\n                    'data' => $view->getData(),\n                ];\n            }\n\n            return [\n                'name' => $view->name(),\n                'path' => $view->getPath(),\n                'params' => $this->paramsService->resolveFlattenFromArray($view->getData()),\n            ];\n        })->values();\n\n        $this->data->put('views', $views);\n    }\n}\n"
  },
  {
    "path": "tests/Feature/CommandsTest.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Feature;\n\nuse Mockery;\nuse GuzzleHttp\\Client;\nuse GuzzleHttp\\Psr7\\Request;\nuse GuzzleHttp\\Psr7\\Response;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Foundation\\Application;\nuse Illuminate\\Support\\Facades\\Artisan;\nuse GuzzleHttp\\Exception\\ConnectException;\nuse JKocik\\Laravel\\Profiler\\Tests\\TestCase;\nuse JKocik\\Laravel\\Profiler\\Contracts\\DataTracker;\nuse JKocik\\Laravel\\Profiler\\Services\\ConfigService;\nuse JKocik\\Laravel\\Profiler\\Services\\ConsoleService;\nuse JKocik\\Laravel\\Profiler\\Events\\ServerConnectionFailed;\nuse JKocik\\Laravel\\Profiler\\Tests\\Support\\Fixtures\\TrackerA;\nuse JKocik\\Laravel\\Profiler\\Tests\\Support\\Fixtures\\TrackerB;\nuse JKocik\\Laravel\\Profiler\\Processors\\StatusCommandProcessor;\nuse JKocik\\Laravel\\Profiler\\Events\\ServerConnectionSuccessful;\nuse Illuminate\\Foundation\\Testing\\Concerns\\InteractsWithConsole;\nuse JKocik\\Laravel\\Profiler\\Events\\ProfilerServerConnectionFailed;\nuse JKocik\\Laravel\\Profiler\\Events\\ProfilerServerConnectionSuccessful;\n\nclass CommandsTest extends TestCase\n{\n    use InteractsWithConsole;\n\n    /**\n     * @return int\n     */\n    protected function countAllConfigurableTrackers(): int\n    {\n        $abstract = 1;\n        $required = 4;\n        $directoryDots = 2;\n        $trackers = scandir(__DIR__ . '/../../src/Trackers/');\n\n        return count($trackers) - $abstract - $required - $directoryDots;\n    }\n\n    /** @test */\n    function tells_status_if_profiler_is_enabled()\n    {\n        $this->tapLaravelVersionFrom(5.7, function () {\n            $this->artisan('profiler:status')\n                ->expectsOutput('1) Your current environment is: ' . $this->app->environment())\n                ->expectsOutput('Laravel Profiler is: enabled');\n        });\n\n        $this->tapLaravelVersionTill(5.6, function () {\n            $this->artisan('profiler:status');\n            $this->assertTrue(true);\n        });\n    }\n\n    /** @test */\n    function lists_trackers_if_profiler_is_enabled()\n    {\n        $this->app = $this->appWith(function (Application $app) {\n            $app->make('config')->set('profiler.trackers', [\n                TrackerA::class,\n                TrackerB::class,\n            ]);\n        });\n\n        $this->tapLaravelVersionFrom(5.7, function () {\n            $this->artisan('profiler:status')\n                ->expectsOutput('2) You have 2 tracker(s) turned on')\n                ->expectsOutput('- ' . TrackerA::class)\n                ->expectsOutput('- ' . TrackerB::class)\n                ->expectsOutput(\"There are {$this->countAllConfigurableTrackers()} trackers available out of the box\")\n                ->expectsOutput('turn them on and off in profiler.php configuration file');\n        });\n\n        $this->tapLaravelVersionTill(5.6, function () {\n            $this->artisan('profiler:status');\n            $this->assertTrue(true);\n        });\n    }\n\n    /** @test */\n    function switches_processor_to_status_processor()\n    {\n        $this->artisan('profiler:status');\n\n        $configService = $this->app->make(ConfigService::class);\n\n        $this->assertCount(1, $configService->processors());\n        $this->assertEquals(StatusCommandProcessor::class, $configService->processors()->first());\n    }\n\n    /** @test */\n    function status_processor_handles_when_connection_to_profiler_server_is_successful()\n    {\n        $this->tapLaravelVersionFrom(5.4, function () {\n            Event::fake();\n\n            $response = Mockery::mock(Response::class);\n            $response->shouldReceive('getBody')->once()->andReturn('{\"sockets\": 1234, \"clients\": 9}');\n\n            $client = Mockery::mock(Client::class);\n            $client->shouldReceive('request')->once()->andReturn($response);\n\n            $configService = Mockery::mock(ConfigService::class);\n            $configService->shouldReceive('serverHttpConnectionUrl')->once();\n\n            $processor = new StatusCommandProcessor($client, $configService);\n            $processor->process($this->app->make(DataTracker::class));\n\n            Event::assertNotDispatched(ProfilerServerConnectionFailed::class);\n            Event::assertDispatched(ProfilerServerConnectionSuccessful::class, function ($event) {\n                return $event->socketsPort === 1234 && $event->countClients === 9;\n            });\n        });\n\n        $this->tapLaravelVersionTill(5.3, function () {\n            $this->assertTrue(true);\n        });\n    }\n\n    /** @test */\n    function status_processor_handles_when_connection_to_profiler_server_failed()\n    {\n        $this->tapLaravelVersionFrom(5.4, function () {\n            Event::fake();\n\n            $client = Mockery::mock(Client::class);\n            $client->shouldReceive('request')->once()->andThrows(new ConnectException('', new Request('method', '')));\n\n            try {\n                $processor = new StatusCommandProcessor($client, $this->app->make(ConfigService::class));\n                $processor->process($this->app->make(DataTracker::class));\n            } catch (ConnectException $e) {\n                Event::assertDispatched(ProfilerServerConnectionFailed::class);\n                Event::assertNotDispatched(ProfilerServerConnectionSuccessful::class);\n                return;\n            }\n\n            $this->fail('ConnectException should be thrown');\n        });\n\n        $this->tapLaravelVersionTill(5.3, function () {\n            $this->assertTrue(true);\n        });\n    }\n\n    /** @test */\n    function tells_if_connection_to_profiler_server_is_successful()\n    {\n        $this->tapLaravelVersionFrom(7, function () {\n            $this->artisan('profiler:status');\n            $this->assertTrue(true);\n        });\n\n        $this->tapLaravelVersionBetween(5.7, 6, function () {\n            $realConsoleService = new ConsoleService($this->app, $this->app->make(ConfigService::class));\n\n            $consoleService = Mockery::mock(ConsoleService::class)->shouldIgnoreMissing();\n            $consoleService->shouldReceive('connectionStatusInfo')\n                ->once()\n                ->andReturn($realConsoleService->connectionStatusInfo());\n            $consoleService->shouldReceive('connectionSuccessfulInfo')\n                ->once()\n                ->andReturn($realConsoleService->connectionSuccessfulInfo());\n            $consoleService->shouldReceive('connectionSuccessfulSocketsInfo')\n                ->once()\n                ->andReturn($realConsoleService->connectionSuccessfulSocketsInfo(1234));\n            $consoleService->shouldReceive('connectionSuccessfulClientsInfo')\n                ->once()\n                ->andReturn($realConsoleService->connectionSuccessfulClientsInfo(9));\n            $consoleService->shouldNotReceive('connectionFailedInfo');\n            $consoleService->shouldNotReceive('connectionStatusUnknownInfo');\n            $this->app->instance(ConsoleService::class, $consoleService);\n\n            $this->app->terminating(function () {\n                event(new ProfilerServerConnectionSuccessful(1234, 9));\n            });\n\n            $this->artisan('profiler:status')\n                ->expectsOutput('3) Trying to connect to Profiler Server on http://localhost:8099 ...')\n                ->expectsOutput('Connected successfully')\n                ->expectsOutput('Profiler Server sockets listening on port: 1234')\n                ->expectsOutput(\"You have 9 Profiler Client(s) connected at the moment\");\n\n            $this->turnOffProcessors();\n            $this->app->terminate();\n        });\n\n        $this->tapLaravelVersionTill(5.6, function () {\n            $this->artisan('profiler:status');\n            $this->assertTrue(true);\n        });\n    }\n\n    /** @test */\n    function tells_if_connection_to_profiler_server_failed()\n    {\n        $this->tapLaravelVersionFrom(7, function () {\n            $this->artisan('profiler:status');\n            $this->assertTrue(true);\n        });\n\n        $this->tapLaravelVersionBetween(5.7, 6, function () {\n            $realConsoleService = new ConsoleService($this->app, $this->app->make(ConfigService::class));\n\n            $consoleService = Mockery::mock(ConsoleService::class)->shouldIgnoreMissing();\n            $consoleService->shouldReceive('connectionStatusInfo')\n                ->once()\n                ->andReturn($realConsoleService->connectionStatusInfo());\n            $consoleService->shouldNotReceive('connectionSuccessfulInfo');\n            $consoleService->shouldReceive('connectionFailedInfo')\n                ->once()\n                ->andReturn($realConsoleService->connectionFailedInfo());\n            $consoleService->shouldNotReceive('connectionStatusUnknownInfo');\n            $this->app->instance(ConsoleService::class, $consoleService);\n\n            $this->app->terminating(function () {\n                event(new ProfilerServerConnectionFailed());\n            });\n\n            $this->artisan('profiler:status')\n                ->expectsOutput('3) Trying to connect to Profiler Server on http://localhost:8099 ...')\n                ->expectsOutput('Connection failed');\n\n            $this->turnOffProcessors();\n            $this->app->terminate();\n\n            $consoleService->shouldNotHaveReceived('connectionUnknownInfo');\n        });\n\n        $this->tapLaravelVersionTill(5.6, function () {\n            $this->artisan('profiler:status');\n            $this->assertTrue(true);\n        });\n    }\n\n    /** @test */\n    function tells_if_connection_to_profiler_server_has_unknown_status()\n    {\n        $this->tapLaravelVersionFrom(7, function () {\n            $this->artisan('profiler:status');\n            $this->assertTrue(true);\n        });\n\n        $this->tapLaravelVersionBetween(5.7, 6, function () {\n            $realConsoleService = new ConsoleService($this->app, $this->app->make(ConfigService::class));\n\n            $consoleService = Mockery::mock(ConsoleService::class)->shouldIgnoreMissing();\n            $consoleService->shouldReceive('connectionStatusInfo')\n                ->once()\n                ->andReturn($realConsoleService->connectionStatusInfo());\n            $consoleService->shouldNotReceive('connectionSuccessfulInfo');\n            $consoleService->shouldNotReceive('connectionFailedInfo');\n            $consoleService->shouldReceive('connectionStatusUnknownInfo')\n                ->once()\n                ->andReturn($realConsoleService->connectionStatusUnknownInfo());\n            $this->app->instance(ConsoleService::class, $consoleService);\n\n            $this->artisan('profiler:status')\n                ->expectsOutput('3) Trying to connect to Profiler Server on http://localhost:8099 ...')\n                ->expectsOutput('BroadcastingProcessor did not report connection status, connection status is unknown');\n\n            $this->turnOffProcessors();\n            $this->app->terminate();\n        });\n\n        $this->tapLaravelVersionTill(5.6, function () {\n            $this->artisan('profiler:status');\n            $this->assertTrue(true);\n        });\n    }\n\n    /** @test */\n    function tells_status_if_profiler_is_disabled()\n    {\n        $this->app = $this->appWith(function (Application $app) {\n            $app->make('config')->set('profiler.enabled', false);\n        });\n\n        $configService = Mockery::spy(ConfigService::class)->shouldIgnoreMissing();\n        $this->app->instance(ConfigService::class, $configService);\n\n        $this->tapLaravelVersionFrom(5.7, function () {\n            $this->artisan('profiler:status')\n                ->expectsOutput('1) Your current environment is: ' . $this->app->environment())\n                ->expectsOutput('Laravel Profiler is: disabled');\n        });\n\n        $this->tapLaravelVersionTill(5.6, function () {\n            $this->artisan('profiler:status');\n            $this->assertTrue(true);\n        });\n\n        $configService->shouldNotHaveReceived('trackers');\n    }\n\n    /** @test */\n    function can_start_profiler_server()\n    {\n        $consoleService = Mockery::spy(ConsoleService::class);\n        $this->app->instance(ConsoleService::class, $consoleService);\n\n        $this->artisan('profiler:server');\n\n        $consoleService->shouldHaveReceived('profilerServerCmd')->once();\n    }\n\n    /** @test */\n    function can_start_profiler_server_with_configured_ports()\n    {\n        $configService = Mockery::mock(ConfigService::class);\n        $configService->shouldReceive('serverHttpPort')->once()->andReturn('1234');\n        $configService->shouldReceive('serverSocketsPort')->once()->andReturn('9876');\n        $this->app->instance(ConfigService::class, $configService);\n\n        $consoleService = $this->app->make(ConsoleService::class);\n\n        $this->assertEquals(\n            'node node_modules/laravel-profiler-client/server/server.js http=1234 ws=9876',\n            $consoleService->profilerServerCmd()\n        );\n    }\n\n    /** @test */\n    function tells_starting_message_for_profiler_server()\n    {\n        $this->tapLaravelVersionFrom(5.7, function () {\n            $this->artisan('profiler:server')\n                ->expectsOutput('Starting Profiler Server ...');\n        });\n\n        $this->tapLaravelVersionTill(5.6, function () {\n            $this->artisan('profiler:server');\n            $this->assertTrue(true);\n        });\n    }\n\n    /** @test */\n    function can_start_profiler_client()\n    {\n        $realConsoleService = $this->app->make(ConsoleService::class);\n\n        $consoleService = Mockery::mock(ConsoleService::class);\n        $consoleService->shouldReceive('profilerClientCmd')->once()->with(false);\n        $this->app->instance(ConsoleService::class, $consoleService);\n\n        Artisan::call('profiler:client');\n\n        $this->assertEquals(\n            'node_modules/.bin/http-server node_modules/laravel-profiler-client/dist/ -o -s',\n            $realConsoleService->profilerClientCmd(false)\n        );\n    }\n\n    /** @test */\n    function can_start_profiler_client_with_manual_option()\n    {\n        $consoleService = Mockery::mock(ConsoleService::class);\n        $consoleService->shouldReceive('profilerClientCmd')->twice()->with(true);\n        $this->app->instance(ConsoleService::class, $consoleService);\n\n        Artisan::call('profiler:client', ['--manual' => true]);\n        Artisan::call('profiler:client', ['-m' => true]);\n\n        $realConsoleService = new ConsoleService($this->app, $this->app->make(ConfigService::class));\n\n        $this->assertEquals(\n            'node_modules/.bin/http-server node_modules/laravel-profiler-client/dist/',\n            $realConsoleService->profilerClientCmd(true)\n        );\n    }\n\n    /** @test */\n    function tells_starting_message_for_profiler_client()\n    {\n        $this->tapLaravelVersionFrom(5.7, function () {\n            $this->artisan('profiler:client')\n                ->expectsOutput('Starting Profiler Client ...');\n        });\n\n        $this->tapLaravelVersionTill(5.6, function () {\n            $this->artisan('profiler:client');\n            $this->assertTrue(true);\n        });\n    }\n\n    /**\n     * @var array\n     */\n    protected $beforeApplicationDestroyedCallbacks = [];\n\n    /**\n     * @param callable $callback\n     */\n    protected function beforeApplicationDestroyed(callable $callback)\n    {\n        $this->beforeApplicationDestroyedCallbacks[] = $callback;\n    }\n}\n"
  },
  {
    "path": "tests/Feature/LaravelConsoleExecutionTest.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Feature;\n\nuse Illuminate\\Support\\Facades\\Artisan;\nuse Illuminate\\Contracts\\Console\\Kernel;\nuse JKocik\\Laravel\\Profiler\\Tests\\TestCase;\nuse JKocik\\Laravel\\Profiler\\Contracts\\ExecutionData;\nuse JKocik\\Laravel\\Profiler\\LaravelExecution\\NullRoute;\nuse JKocik\\Laravel\\Profiler\\LaravelExecution\\NullServer;\nuse JKocik\\Laravel\\Profiler\\LaravelExecution\\NullContent;\nuse JKocik\\Laravel\\Profiler\\LaravelExecution\\NullSession;\nuse JKocik\\Laravel\\Profiler\\Tests\\Support\\Fixtures\\DummyCommand;\nuse JKocik\\Laravel\\Profiler\\LaravelExecution\\ConsoleFinishedRequest;\nuse JKocik\\Laravel\\Profiler\\LaravelExecution\\ConsoleStartingRequest;\nuse JKocik\\Laravel\\Profiler\\LaravelExecution\\ConsoleFinishedResponse;\nuse JKocik\\Laravel\\Profiler\\LaravelExecution\\ConsoleStartingResponse;\n\nclass LaravelConsoleExecutionTest extends TestCase\n{\n    /**\n     * @var ExecutionData\n     */\n    protected $executionData;\n\n    /**\n     * @var int\n     */\n    protected $testExitCode = 123;\n\n    /**\n     * @return void\n     */\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $this->turnOffProcessors();\n\n        $this->executionData = $this->app->make(ExecutionData::class);\n\n        $this->app->make(Kernel::class)->registerCommand(new DummyCommand($this->testExitCode));\n    }\n\n    /** @test */\n    function has_console_request()\n    {\n        Artisan::call('dummy-command');\n        $request = $this->executionData->request();\n\n        $this->tapLaravelVersionTill(5.4, function () use ($request) {\n            $this->assertInstanceOf(ConsoleStartingRequest::class, $request);\n        });\n\n        $this->tapLaravelVersionFrom(5.5, function () use ($request) {\n            $this->assertInstanceOf(ConsoleFinishedRequest::class, $request);\n        });\n    }\n\n    /** @test */\n    function has_request_type()\n    {\n        Artisan::call('dummy-command');\n        $request = $this->executionData->request();\n\n        $this->tapLaravelVersionTill(5.4, function () use ($request) {\n            $this->assertEquals('command-starting', $request->meta()->get('type'));\n        });\n\n        $this->tapLaravelVersionFrom(5.5, function () use ($request) {\n            $this->assertEquals('command-finished', $request->meta()->get('type'));\n        });\n    }\n\n    /** @test */\n    function has_request_method()\n    {\n        Artisan::call('dummy-command');\n        $request = $this->executionData->request();\n\n        $this->tapLaravelVersionTill(5.4, function () use ($request) {\n            $this->assertArrayNotHasKey('path', $request->meta());\n        });\n\n        $this->tapLaravelVersionFrom(5.5, function () use ($request) {\n            $this->assertEquals('dummy-command', $request->meta()->get('path'));\n        });\n    }\n\n    /** @test */\n    function has_request_arguments()\n    {\n        Artisan::call('dummy-command', ['user' => 'Abc']);\n        $request = $this->executionData->request();\n\n        $this->tapLaravelVersionTill(5.4, function () use ($request) {\n            $this->assertArrayNotHasKey('arguments', $request->data());\n        });\n\n        $this->tapLaravelVersionFrom(5.5, function () use ($request) {\n            $this->assertEquals('dummy-command', $request->data()->get('arguments')['command']);\n            $this->assertEquals('Abc', $request->data()->get('arguments')['user']);\n        });\n    }\n\n    /** @test */\n    function has_request_options()\n    {\n        Artisan::call('dummy-command', ['--number' => 5]);\n        $request = $this->executionData->request();\n\n        $this->tapLaravelVersionTill(5.4, function () use ($request) {\n            $this->assertArrayNotHasKey('options', $request->data());\n        });\n\n        $this->tapLaravelVersionFrom(5.5, function () use ($request) {\n            $this->assertEquals(5, $request->data()->get('options')['number']);\n        });\n    }\n\n    /** @test */\n    function has_null_route()\n    {\n        Artisan::call('dummy-command');\n        $route = $this->executionData->route();\n\n        $this->assertInstanceOf(NullRoute::class, $route);\n    }\n\n    /** @test */\n    function has_null_session()\n    {\n        Artisan::call('dummy-command');\n        $session = $this->executionData->session();\n\n        $this->assertInstanceOf(NullSession::class, $session);\n    }\n\n    /** @test */\n    function has_null_server()\n    {\n        Artisan::call('dummy-command');\n        $server = $this->executionData->server();\n\n        $this->assertInstanceOf(NullServer::class, $server);\n    }\n\n    /** @test */\n    function has_console_response()\n    {\n        Artisan::call('dummy-command');\n        $response = $this->executionData->response();\n\n        $this->tapLaravelVersionTill(5.4, function () use ($response) {\n            $this->assertInstanceOf(ConsoleStartingResponse::class, $response);\n        });\n\n        $this->tapLaravelVersionFrom(5.5, function () use ($response) {\n            $this->assertInstanceOf(ConsoleFinishedResponse::class, $response);\n        });\n    }\n\n    /** @test */\n    function console_response_has_only_status()\n    {\n        Artisan::call('dummy-command');\n        $response = $this->executionData->response();\n\n        $this->tapLaravelVersionTill(5.4, function () use ($response) {\n            $this->assertArrayHasKey('status', $response->meta());\n            $this->assertNull($response->meta()->get('status'));\n            $this->assertCount(1, $response->meta());\n            $this->assertCount(0, $response->data());\n        });\n\n        $this->tapLaravelVersionFrom(5.5, function () use ($response) {\n            $this->assertEquals($this->testExitCode, $response->meta()->get('status'));\n            $this->assertCount(1, $response->meta());\n            $this->assertCount(0, $response->data());\n        });\n    }\n\n    /** @test */\n    function has_null_content()\n    {\n        Artisan::call('dummy-command');\n        $content = $this->executionData->content();\n\n        $this->assertInstanceOf(NullContent::class, $content);\n    }\n}\n"
  },
  {
    "path": "tests/Feature/LaravelExecutionTest.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Feature;\n\nuse JKocik\\Laravel\\Profiler\\Tests\\TestCase;\nuse JKocik\\Laravel\\Profiler\\Contracts\\ExecutionData;\n\nclass LaravelExecutionTest extends TestCase\n{\n    /**\n     * @return void\n     */\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $this->turnOffProcessors();\n    }\n\n    /** @test */\n    function laravel_execution_data_is_singleton()\n    {\n        $executionDataA = $this->app->make(ExecutionData::class);\n        $executionDataB = $this->app->make(ExecutionData::class);\n\n        $this->assertSame($executionDataA, $executionDataB);\n    }\n}\n"
  },
  {
    "path": "tests/Feature/LaravelHttpExecutionTest.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Feature;\n\nuse ReflectionMethod;\nuse ReflectionFunction;\nuse ReflectionException;\nuse Illuminate\\Http\\UploadedFile;\nuse Illuminate\\Support\\Facades\\Crypt;\nuse Illuminate\\Support\\Facades\\Route;\nuse JKocik\\Laravel\\Profiler\\Tests\\TestCase;\nuse JKocik\\Laravel\\Profiler\\Contracts\\ExecutionData;\nuse JKocik\\Laravel\\Profiler\\LaravelExecution\\HttpRoute;\nuse JKocik\\Laravel\\Profiler\\LaravelExecution\\NullRoute;\nuse JKocik\\Laravel\\Profiler\\LaravelExecution\\HttpRequest;\nuse JKocik\\Laravel\\Profiler\\LaravelExecution\\HttpSession;\nuse JKocik\\Laravel\\Profiler\\LaravelExecution\\HttpResponse;\nuse JKocik\\Laravel\\Profiler\\Tests\\Support\\Fixtures\\DummyClassA;\nuse JKocik\\Laravel\\Profiler\\Tests\\Support\\Fixtures\\DummyController;\nuse JKocik\\Laravel\\Profiler\\Tests\\Support\\Fixtures\\DummyFormRequest;\n\nclass LaravelHttpExecutionTest extends TestCase\n{\n    /**\n     * @var ExecutionData\n     */\n    protected $executionData;\n\n    /**\n     * @return void\n     */\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $this->turnOffProcessors();\n\n        $this->executionData = $this->app->make(ExecutionData::class);\n    }\n\n    /** @test */\n    function has_http_request()\n    {\n        $this->get('/');\n        $request = $this->executionData->request();\n\n        $this->assertInstanceOf(HttpRequest::class, $request);\n    }\n\n    /** @test */\n    function has_request_type()\n    {\n        $this->get('/');\n        $request = $this->executionData->request();\n\n        $this->assertEquals('http', $request->meta()->get('type'));\n    }\n\n    /** @test */\n    function has_request_method()\n    {\n        $this->post('/', []);\n        $request = $this->executionData->request();\n\n        $this->assertEquals('POST', $request->meta()->get('method'));\n    }\n\n    /** @test */\n    function has_request_path()\n    {\n        $this->get('/abc/xyz');\n        $request = $this->executionData->request();\n\n        $this->assertEquals('abc/xyz', $request->meta()->get('path'));\n    }\n\n    /** @test */\n    function has_request_is_ajax()\n    {\n        $this->get('/');\n        $this->assertFalse($this->executionData->request()->meta()->get('ajax'));\n\n        $this->get('/', ['X-Requested-With' => 'XMLHttpRequest']);\n        $this->assertTrue($this->executionData->request()->meta()->get('ajax'));\n    }\n\n    /** @test */\n    function has_request_is_json()\n    {\n        $this->get('/');\n        $this->assertFalse($this->executionData->request()->meta()->get('json'));\n\n        $this->get('/', ['Content-Type' => 'application/json']);\n        $this->assertTrue($this->executionData->request()->meta()->get('json'));\n    }\n\n    /** @test */\n    function has_request_is_pjax()\n    {\n        $this->get('/');\n        $this->assertFalse($this->executionData->request()->data()->get('pjax'));\n\n        $this->get('/', ['X-PJAX' => true]);\n        $this->assertTrue($this->executionData->request()->data()->get('pjax'));\n    }\n\n    /** @test */\n    function has_request_url()\n    {\n        $this->get('/abc?ab=xy');\n        $request = $this->executionData->request();\n\n        $this->assertEquals(\"{$this->app->make('request')->root()}/abc\", $request->data()->get('url'));\n    }\n\n    /** @test */\n    function has_request_query()\n    {\n        $this->get('/abc?ab=xy');\n        $this->assertEquals(['ab' => 'xy'], $this->executionData->request()->data()->get('query'));\n    }\n\n    /** @test */\n    function can_have_empty_request_query()\n    {\n        $this->get('/');\n        $this->assertEquals([], $this->executionData->request()->data()->get('query'));\n    }\n\n    /** @test */\n    function has_request_ip()\n    {\n        $this->get('/');\n        $request = $this->executionData->request();\n\n        $this->assertEquals($this->app->make('request')->ip(), $request->data()->get('ip'));\n    }\n\n    /** @test */\n    function has_request_server()\n    {\n        $this->get('/');\n        $server = $this->executionData->server();\n\n        $this->assertCount(0, $server->meta());\n        $this->assertEquals($this->app->make('request')->server(), $server->data()->toArray());\n    }\n\n    /** @test */\n    function has_request_header()\n    {\n        $this->get('/');\n        $request = $this->executionData->request();\n\n        $this->assertEquals($this->app->make('request')->header(), $request->data()->get('header'));\n    }\n\n    /** @test */\n    function has_request_input()\n    {\n        $this->post('/', [\n            'key-a' => 'val-a',\n            'key-b' => 'val-b',\n        ]);\n        $request = $this->executionData->request();\n\n        $this->assertEquals('val-a', $request->data()->get('input')['key-a']);\n        $this->assertEquals('val-b', $request->data()->get('input')['key-b']);\n    }\n\n    /** @test */\n    function has_request_all_files()\n    {\n        $this->tapLaravelVersionTill(5.3, function () {\n            $this->assertTrue(true);\n        });\n\n        $this->tapLaravelVersionBetween(5.4, 6, function () {\n            $fileA = UploadedFile::fake()->image('file-val-a.png');\n            $fileB = UploadedFile::fake()->image('file-val-b.png');\n            $typeA = get_class($fileA);\n            $typeB = get_class($fileB);\n\n            $this->post('/', [\n                'file-key-a' => $fileA,\n                'file-key-b' => $fileB,\n            ]);\n\n            $request = $this->executionData->request();\n\n            $this->assertEquals([\n                'client original name' => $fileA->getClientOriginalName(),\n                'client original extension' => $fileA->getClientOriginalExtension(),\n                'client mime type' => $fileA->getClientMimeType(),\n                'client size' => $fileA->getClientSize(),\n                'path' => $fileA->path(),\n            ], $request->data()->get('files')['file-key-a'][$typeA]);\n            $this->assertEquals([\n                'client original name' => $fileB->getClientOriginalName(),\n                'client original extension' => $fileB->getClientOriginalExtension(),\n                'client mime type' => $fileB->getClientMimeType(),\n                'client size' => $fileB->getClientSize(),\n                'path' => $fileB->path(),\n            ], $request->data()->get('files')['file-key-b'][$typeB]);\n        });\n\n        $this->tapLaravelVersionFrom(7, function () {\n            $fileA = UploadedFile::fake()->image('file-val-a.png');\n            $fileB = UploadedFile::fake()->image('file-val-b.png');\n            $typeA = get_class($fileA);\n            $typeB = get_class($fileB);\n\n            $this->post('/', [\n                'file-key-a' => $fileA,\n                'file-key-b' => $fileB,\n            ]);\n\n            $request = $this->executionData->request();\n\n            $this->assertEquals([\n                'client original name' => $fileA->getClientOriginalName(),\n                'client original extension' => $fileA->getClientOriginalExtension(),\n                'client mime type' => $fileA->getClientMimeType(),\n                'client size' => $fileA->getSize(),\n                'path' => $fileA->path(),\n            ], $request->data()->get('files')['file-key-a'][$typeA]);\n            $this->assertEquals([\n                'client original name' => $fileB->getClientOriginalName(),\n                'client original extension' => $fileB->getClientOriginalExtension(),\n                'client mime type' => $fileB->getClientMimeType(),\n                'client size' => $fileB->getSize(),\n                'path' => $fileB->path(),\n            ], $request->data()->get('files')['file-key-b'][$typeB]);\n        });\n    }\n\n    /** @test */\n    function has_request_all_files_if_they_are_in_array()\n    {\n        $this->tapLaravelVersionTill(5.3, function () {\n            $this->assertTrue(true);\n        });\n\n        $this->tapLaravelVersionFrom(5.4, function () {\n            $fileA = UploadedFile::fake()->image('file-val-a.png');\n            $fileB = UploadedFile::fake()->image('file-val-b.png');\n            $fileX = UploadedFile::fake()->image('file-val-x.png');\n            $fileY = UploadedFile::fake()->image('file-val-y.png');\n            $typeA = get_class($fileA);\n            $typeB = get_class($fileB);\n            $typeX = get_class($fileX);\n            $typeY = get_class($fileY);\n\n            $this->post('/', [\n                'file-key-1' => [\n                    'a' => $fileA,\n                    'b' => $fileB,\n                ],\n                'file-key-2' => [\n                    'subkey' => [\n                        'x' => $fileX,\n                        'y' => $fileY,\n                    ],\n                ],\n            ]);\n\n            $request = $this->executionData->request();\n\n            $this->assertContains($fileA->path(), $request->data()->get('files')['file-key-1']['a'][$typeA]);\n            $this->assertContains($fileB->path(), $request->data()->get('files')['file-key-1']['b'][$typeB]);\n            $this->assertContains($fileX->path(), $request->data()->get('files')['file-key-2']['subkey']['x'][$typeX]);\n            $this->assertContains($fileY->path(), $request->data()->get('files')['file-key-2']['subkey']['y'][$typeY]);\n        });\n    }\n\n    /** @test */\n    function has_request_cookie()\n    {\n        $this->tapLaravelVersionTill('5.4', function () {\n            $this->call('GET', '/', [], ['cookie-key-a' => Crypt::encrypt('cookie-val-a')]);\n            $request = $this->executionData->request();\n\n            $this->assertStringContainsString('cookie-val-a', $request->data()->get('cookie')['cookie-key-a']);\n        });\n\n        $this->tapLaravelVersionBetween('5.5', '5.5', function () {\n            $this->call('GET', '/', [], ['cookie-key-a' => [Crypt::encrypt('cookie-val-a')]]);\n            $request = $this->executionData->request();\n\n            $this->assertStringContainsString('cookie-val-a', Crypt::decrypt($request->data()->get('cookie')['cookie-key-a'][0]));\n        });\n\n        $this->tapLaravelVersionBetween('5.6', '5.8', function () {\n            $this->call('GET', '/', [], ['cookie-key-a' => Crypt::encrypt('cookie-val-a')]);\n            $request = $this->executionData->request();\n\n            $this->assertStringContainsString('cookie-val-a', $request->data()->get('cookie')['cookie-key-a']);\n        });\n\n        $this->tapLaravelVersionFrom('6', function () {\n            $this->call('GET', '/', [], ['cookie-key-a' => [Crypt::encrypt('cookie-val-a')]]);\n            $request = $this->executionData->request();\n\n            $this->assertStringContainsString('cookie-val-a', Crypt::decrypt($request->data()->get('cookie')['cookie-key-a'][0]));\n        });\n    }\n\n    /** @test */\n    function has_http_route()\n    {\n        $this->get('/');\n        $route = $this->executionData->route();\n\n        $this->assertInstanceOf(HttpRoute::class, $route);\n    }\n\n    /** @test */\n    function has_null_route_when_route_is_not_matched()\n    {\n        $this->get('/not-found');\n        $route = $this->executionData->route();\n\n        $this->assertInstanceOf(NullRoute::class, $route);\n    }\n\n    /** @test */\n    function has_route_methods()\n    {\n        Route::get('route-a/{id}', function ($id) {\n            return $id;\n        });\n\n        $this->get('/route-a/123');\n        $route = $this->executionData->route();\n\n        $this->assertEquals(['GET', 'HEAD'], $route->data()->get('methods'));\n    }\n\n    /** @test */\n    function has_route_uri()\n    {\n        Route::get('route-a/{id}', function ($id) {\n            return $id;\n        });\n\n        $this->get('/route-a/123');\n        $route = $this->executionData->route();\n\n        $this->assertEquals('route-a/{id}', $route->data()->get('uri'));\n    }\n\n    /** @test */\n    function has_route_name()\n    {\n        Route::get('route-a/{id}', function ($id) {\n            return $id;\n        })->name('route.a.with.id');\n\n        $this->get('/route-a/123');\n        $route = $this->executionData->route();\n\n        $this->assertEquals('route.a.with.id', $route->data()->get('name'));\n    }\n\n    /** @test */\n    function has_route_middleware()\n    {\n        Route::get('route-a/{id}', function ($id) {\n            return $id;\n        })->middleware('auth');\n\n        $this->get('/route-a/123');\n        $route = $this->executionData->route();\n\n        $this->assertEquals(['auth'], $route->data()->get('middleware'));\n    }\n\n    /** @test */\n    function has_route_parameters()\n    {\n        Route::get('route-a/{id}', function ($id) {\n            return $id;\n        });\n\n        $this->get('/route-a/123');\n        $route = $this->executionData->route();\n\n        $this->assertEquals(['id' => '123'], $route->data()->get('parameters'));\n    }\n\n    /** @test */\n    function has_route_prefix()\n    {\n        Route::group(['prefix' => 'admin'], function () {\n            Route::get('route-a/{id}', function ($id) {\n                return $id;\n            });\n        });\n\n        $this->get('/admin/route-a/123');\n        $route = $this->executionData->route();\n\n        $this->assertEquals('admin', $route->data()->get('prefix'));\n    }\n\n    /** @test */\n    function has_route_closure_action()\n    {\n        $uses = function (DummyClassA $a, DummyFormRequest $request) {\n            return $request->get('id');\n        };\n        $action = new ReflectionFunction($uses);\n\n        Route::get('route-a/{id}', $uses);\n\n        $this->get('/route-a/123');\n        $route = $this->executionData->route();\n\n        $this->assertStringContainsString(\n            'LaravelHttpExecutionTest.php:' . $action->getStartLine() . '-' . $action->getEndLine(),\n            $route->data()->get('uses')['closure']\n        );\n        $this->assertEquals(\n            DummyFormRequest::class,\n            $route->data()->get('uses')['form_request']\n        );\n    }\n\n    /** @test */\n    function has_route_controller_action()\n    {\n        Route::get('route-a/{id}', '\\JKocik\\Laravel\\Profiler\\Tests\\Support\\Fixtures\\DummyController@dummyAction');\n        $action = new ReflectionMethod(DummyController::class, 'dummyAction');\n\n        $this->get('/route-a/123');\n        $route = $this->executionData->route();\n\n        $this->assertStringContainsString(\n            'DummyController@dummyAction:' . $action->getStartLine() . '-' . $action->getEndLine(),\n            $route->data()->get('uses')['controller']\n        );\n        $this->assertEquals(\n            DummyFormRequest::class,\n            $route->data()->get('uses')['form_request']\n        );\n    }\n\n    /** @test */\n    function has_route_without_form_request_if_form_request_is_not_defined()\n    {\n        $uses = function ($id) {\n            return $id;\n        };\n\n        Route::get('route-a/{id}', $uses);\n\n        $this->get('/route-a/123');\n        $route = $this->executionData->route();\n\n        $this->assertEquals('', $route->data()->get('uses')['form_request']);\n    }\n\n    /** @test */\n    function has_route_with_not_existing_controller()\n    {\n        Route::get('route-a/{id}', '\\JKocik\\Laravel\\Profiler\\Tests\\Support\\Fixtures\\NotExistingController@dummyAction');\n\n        $this->tapLaravelVersionTill(5.2, function () {\n            $this->get('/route-a/123');\n            $route = $this->executionData->route();\n\n            $this->assertInstanceOf(NullRoute::class, $route);\n        });\n\n        $this->tapLaravelVersionBetween(5.3, 5.3, function () {\n            try {\n                $this->get('/route-a/123');\n            } catch (ReflectionException $e) {\n                $this->assertTrue(true);\n            }\n        });\n\n        $this->tapLaravelVersionFrom(5.4, function () {\n            $this->get('/route-a/123');\n            $route = $this->executionData->route();\n\n            $this->assertEquals([], $route->data()->get('uses'));\n        });\n    }\n\n    /** @test */\n    function has_http_session()\n    {\n        $this->get('/');\n        $session = $this->executionData->session();\n\n        $this->assertInstanceOf(HttpSession::class, $session);\n    }\n\n    /** @test */\n    function has_http_session_data()\n    {\n        $this->withSession([\n            'abc' => 123,\n            'xyz' => 789,\n        ])->get('/');\n        $session = $this->executionData->session();\n\n        $this->assertEquals(123, $session->data()->get('abc'));\n        $this->assertEquals(789, $session->data()->get('xyz'));\n    }\n\n    /** @test */\n    function has_http_response()\n    {\n        $this->get('/');\n        $response = $this->executionData->response();\n\n        $this->assertInstanceOf(HttpResponse::class, $response);\n    }\n\n    /** @test */\n    function has_response_status()\n    {\n        $this->get('/i-can-not-find-that-page');\n        $response = $this->executionData->response();\n\n        $this->assertEquals(404, $response->meta()->get('status'));\n        $this->assertEquals('Not Found', $response->meta()->get('status_text'));\n    }\n\n    /** @test */\n    function can_have_response_unknown_status()\n    {\n        Route::get('unknown', function () {\n            abort(419);\n        });\n\n        $this->get('/unknown');\n        $response = $this->executionData->response();\n\n        $this->assertEquals(419, $response->meta()->get('status'));\n        $this->assertEquals('unknown status', $response->meta()->get('status_text'));\n    }\n\n    /** @test */\n    function has_response_headers()\n    {\n        $this->get('/');\n        $response = $this->executionData->response();\n\n        $this->assertArrayHasKey('content-type', $response->data()->get('headers'));\n    }\n\n    /** @test */\n    function has_response_content()\n    {\n        $this->get('/');\n        $content = $this->executionData->content();\n\n        $this->assertCount(0, $content->meta());\n        $this->assertStringNotContainsString('HTTP/1.1 200 OK', $content->data()->get('content'));\n        $this->assertStringContainsString('</body>', $content->data()->get('content'));\n        $this->assertStringContainsString('</html>', $content->data()->get('content'));\n    }\n}\n"
  },
  {
    "path": "tests/Feature/LaravelNullExecutionTest.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Feature;\n\nuse JKocik\\Laravel\\Profiler\\Tests\\TestCase;\nuse JKocik\\Laravel\\Profiler\\Contracts\\ExecutionData;\nuse JKocik\\Laravel\\Profiler\\LaravelExecution\\NullRoute;\nuse JKocik\\Laravel\\Profiler\\LaravelExecution\\NullServer;\nuse JKocik\\Laravel\\Profiler\\LaravelExecution\\NullContent;\nuse JKocik\\Laravel\\Profiler\\LaravelExecution\\NullRequest;\nuse JKocik\\Laravel\\Profiler\\LaravelExecution\\NullSession;\nuse JKocik\\Laravel\\Profiler\\LaravelExecution\\NullResponse;\n\nclass LaravelNullExecutionTest extends TestCase\n{\n    /**\n     * @var ExecutionData\n     */\n    protected $executionData;\n\n    /**\n     * @return void\n     */\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $this->turnOffProcessors();\n\n        $this->executionData = $this->app->make(ExecutionData::class);\n    }\n\n\n    /** @test */\n    function has_null_request()\n    {\n        $request = $this->executionData->request();\n\n        $this->assertInstanceOf(NullRequest::class, $request);\n    }\n\n    /** @test */\n    function null_request_has_only_type()\n    {\n        $request = $this->executionData->request();\n\n        $this->assertTrue($request->meta()->has('type'));\n        $this->assertNull($request->meta()->get('type'));\n        $this->assertCount(1, $request->meta());\n        $this->assertCount(0, $request->data());\n    }\n\n    /** @test */\n    function has_null_route()\n    {\n        $route = $this->executionData->route();\n\n        $this->assertInstanceOf(NullRoute::class, $route);\n    }\n\n    /** @test */\n    function null_route_is_empty()\n    {\n        $route = $this->executionData->route();\n\n        $this->assertCount(0, $route->meta());\n        $this->assertCount(0, $route->data());\n    }\n\n    /** @test */\n    function has_null_session()\n    {\n        $session = $this->executionData->session();\n\n        $this->assertInstanceOf(NullSession::class, $session);\n    }\n\n    /** @test */\n    function null_session_is_empty()\n    {\n        $session = $this->executionData->session();\n\n        $this->assertCount(0, $session->meta());\n        $this->assertCount(0, $session->data());\n    }\n\n    /** @test */\n    function has_null_server()\n    {\n        $server = $this->executionData->server();\n\n        $this->assertInstanceOf(NullServer::class, $server);\n    }\n\n    /** @test */\n    function null_server_is_empty()\n    {\n        $server = $this->executionData->server();\n\n        $this->assertCount(0, $server->meta());\n        $this->assertCount(0, $server->data());\n    }\n\n    /** @test */\n    function has_null_response()\n    {\n        $response = $this->executionData->response();\n\n        $this->assertInstanceOf(NullResponse::class, $response);\n    }\n\n    /** @test */\n    function null_response_is_empty()\n    {\n        $response = $this->executionData->response();\n\n        $this->assertCount(0, $response->meta());\n        $this->assertCount(0, $response->data());\n    }\n\n    /** @test */\n    function has_null_content()\n    {\n        $content = $this->executionData->content();\n\n        $this->assertInstanceOf(NullContent::class, $content);\n    }\n\n    /** @test */\n    function null_content_is_empty()\n    {\n        $content = $this->executionData->content();\n\n        $this->assertCount(0, $content->meta());\n        $this->assertCount(0, $content->data());\n    }\n}\n"
  },
  {
    "path": "tests/Feature/PerformanceTest.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Feature;\n\nuse JKocik\\Laravel\\Profiler\\Tests\\TestCase;\nuse JKocik\\Laravel\\Profiler\\Contracts\\Timer;\nuse JKocik\\Laravel\\Profiler\\Contracts\\Memory;\nuse JKocik\\Laravel\\Profiler\\Services\\Performance\\TimerService;\nuse JKocik\\Laravel\\Profiler\\Services\\Performance\\NullTimerService;\n\nclass PerformanceTest extends TestCase\n{\n    /** @test */\n    function enabled_profiler_has_singleton_timer()\n    {\n        $timerA = $this->app->make(Timer::class);\n        $timerB = $this->app->make(Timer::class);\n\n        $this->assertInstanceOf(TimerService::class, $timerA);\n        $this->assertSame($timerA, $timerB);\n    }\n\n    /** @test */\n    function disabled_profiler_has_singleton_null_timer()\n    {\n        putenv('PROFILER_ENABLED=false');\n        $_ENV['PROFILER_ENABLED'] = false;\n        $this->app = $this->app();\n        $timerA = $this->app->make(Timer::class);\n        $timerB = $this->app->make(Timer::class);\n\n        $this->assertInstanceOf(NullTimerService::class, $timerA);\n        $this->assertSame($timerA, $timerB);\n    }\n\n    /** @test */\n    function memory_is_singleton()\n    {\n        $memoryA = $this->app->make(Memory::class);\n        $memoryB = $this->app->make(Memory::class);\n\n        $this->assertInstanceOf(Memory::class, $memoryA);\n        $this->assertSame($memoryA, $memoryB);\n    }\n\n    /**\n     * @return void\n     */\n    protected function tearDown(): void\n    {\n        parent::tearDown();\n\n        putenv('PROFILER_ENABLED');\n        unset($_ENV['PROFILER_ENABLED']);\n    }\n}\n"
  },
  {
    "path": "tests/Feature/PerformanceTrackerTest.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Feature;\n\nuse Illuminate\\Foundation\\Application;\nuse Illuminate\\Support\\Facades\\Artisan;\nuse Illuminate\\Contracts\\Console\\Kernel;\nuse JKocik\\Laravel\\Profiler\\Tests\\TestCase;\nuse JKocik\\Laravel\\Profiler\\Contracts\\Timer;\nuse JKocik\\Laravel\\Profiler\\Tests\\Support\\PHPMock;\nuse JKocik\\Laravel\\Profiler\\Tests\\Support\\Fixtures\\DummyCommand;\nuse JKocik\\Laravel\\Profiler\\Tests\\Support\\Fixtures\\PerformanceProcessor;\n\nclass PerformanceTrackerTest extends TestCase\n{\n    /**\n     * @return void\n     */\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $this->addFixturePerformanceProcessor();\n    }\n\n    /**\n     * @return void\n     */\n    protected function addFixturePerformanceProcessor(): void\n    {\n        $this->app = $this->appWith(function (Application $app) {\n            $app->make('config')->set('profiler.processors', [\n                PerformanceProcessor::class,\n            ]);\n            $app->singleton(PerformanceProcessor::class, function () {\n                return new PerformanceProcessor();\n            });\n        });\n    }\n\n    /** @test */\n    function has_laravel_total_execution_time()\n    {\n        $this->app->terminate();\n        $timer = $this->app->make(Timer::class);\n        $processor = $this->app->make(PerformanceProcessor::class);\n\n        $this->assertTrue($processor->performance->has('timer'));\n        $this->assertGreaterThan(0, $timer->milliseconds('laravel'));\n        $this->assertEquals($timer->milliseconds('laravel'), $processor->performance->get('timer')['laravel']);\n    }\n\n    /** @test */\n    function has_booting_time()\n    {\n        $this->app->terminate();\n        $timer = $this->app->make(Timer::class);\n        $processor = $this->app->make(PerformanceProcessor::class);\n\n        $this->assertGreaterThan(0, $timer->milliseconds('boot'));\n        $this->assertEquals($timer->milliseconds('boot'), $processor->performance->get('timer')['boot']);\n    }\n\n    /** @test */\n    function has_route_time()\n    {\n        $this->get('/');\n        $timer = $this->app->make(Timer::class);\n        $processor = $this->app->make(PerformanceProcessor::class);\n\n        $this->assertGreaterThan(0, $timer->milliseconds('route'));\n        $this->assertEquals($timer->milliseconds('route'), $processor->performance->get('timer')['route']);\n    }\n\n    /** @test */\n    function has_setup_time_instead_of_route_when_testing()\n    {\n        $this->tapLaravelVersionTill(6, function () {\n            putenv('APP_ENV=testing');\n            $_ENV['APP_ENV'] = 'testing';\n            $this->app = $this->app();\n            $this->addFixturePerformanceProcessor();\n\n            $this->get('/');\n            $timer = $this->app->make(Timer::class);\n            $processor = $this->app->make(PerformanceProcessor::class);\n\n            $this->assertGreaterThan(0, $timer->milliseconds('setup'));\n            $this->assertEquals($timer->milliseconds('setup'), $processor->performance->get('timer')['setup']);\n        });\n\n        $this->tapLaravelVersionFrom(7, function () {\n            $this->assertTrue(true);\n        });\n    }\n\n    /** @test */\n    function has_handle_request_time()\n    {\n        $this->get('/');\n        $timer = $this->app->make(Timer::class);\n        $processor = $this->app->make(PerformanceProcessor::class);\n\n        $this->assertGreaterThan(0, $timer->milliseconds('request'));\n        $this->assertEquals($timer->milliseconds('request'), $processor->performance->get('timer')['request']);\n    }\n\n    /** @test */\n    function has_send_response_and_terminate_time()\n    {\n        $this->get('/');\n        $timer = $this->app->make(Timer::class);\n        $processor = $this->app->make(PerformanceProcessor::class);\n\n        $this->assertGreaterThan(0, $timer->milliseconds('response'));\n        $this->assertEquals($timer->milliseconds('response'), $processor->performance->get('timer')['response']);\n    }\n\n    /** @test */\n    function has_console_time()\n    {\n        $this->app->make(Kernel::class)->registerCommand(new DummyCommand(0));\n        Artisan::call('dummy-command');\n        $this->app->terminate();\n        $timer = $this->app->make(Timer::class);\n        $processor = $this->app->make(PerformanceProcessor::class);\n\n        $this->assertGreaterThan(0, $timer->milliseconds('command'));\n        $this->assertEquals($timer->milliseconds('command'), $processor->performance->get('timer')['command']);\n    }\n\n    /** @test */\n    function has_memory_peak()\n    {\n        $this->app->terminate();\n        $processor = $this->app->make(PerformanceProcessor::class);\n\n        $this->assertEquals(PHPMock::MEMORY_USAGE, $processor->performance->get('memory')['peak']);\n    }\n\n    /**\n     * @return void\n     */\n    protected function tearDown(): void\n    {\n        parent::tearDown();\n\n        putenv('APP_ENV=local');\n        unset($_ENV['APP_ENV']);\n    }\n}\n"
  },
  {
    "path": "tests/Feature/RegisterProfilerTest.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Feature;\n\nuse Mockery;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Foundation\\Application;\nuse Illuminate\\Contracts\\Console\\Kernel;\nuse JKocik\\Laravel\\Profiler\\Tests\\TestCase;\nuse JKocik\\Laravel\\Profiler\\Contracts\\Timer;\nuse JKocik\\Laravel\\Profiler\\ServiceProvider;\nuse JKocik\\Laravel\\Profiler\\LaravelProfiler;\nuse JKocik\\Laravel\\Profiler\\DisabledProfiler;\nuse JKocik\\Laravel\\Profiler\\Contracts\\Profiler;\nuse JKocik\\Laravel\\Profiler\\Events\\Terminating;\nuse JKocik\\Laravel\\Profiler\\Events\\ProfilerBound;\nuse JKocik\\Laravel\\Profiler\\Contracts\\DataTracker;\nuse JKocik\\Laravel\\Profiler\\Contracts\\DataProcessor;\nuse Illuminate\\Foundation\\Bootstrap\\RegisterProviders;\nuse JKocik\\Laravel\\Profiler\\Services\\Performance\\TimerService;\nuse JKocik\\Laravel\\Profiler\\Services\\Performance\\NullTimerService;\nuse JKocik\\Laravel\\Profiler\\LaravelListeners\\HttpRequestHandledListener;\nuse JKocik\\Laravel\\Profiler\\LaravelListeners\\ConsoleCommandFinishedListener;\n\nclass RegisterProfilerTest extends TestCase\n{\n    /**\n     * @param Application $app\n     * @param Timer $timer\n     * @param DataTracker $dataTracker\n     * @param DataProcessor $dataProcessor\n     * @return void\n     */\n    protected function registerServiceProviderWith(\n        Application $app,\n        Timer $timer,\n        DataTracker $dataTracker,\n        DataProcessor $dataProcessor\n    ): void {\n        $provider = new class($app, $timer, $dataTracker, $dataProcessor) extends ServiceProvider {\n            public function __construct(\n                Application $app,\n                Timer $timer,\n                DataTracker $dataTracker,\n                DataProcessor $dataProcessor\n            ) {\n                parent::__construct($app);\n                $this->timer = $timer;\n                $this->dataTracker = $dataTracker;\n                $this->dataProcessor = $dataProcessor;\n            }\n            public function register(): void {\n                Event::listen(ProfilerBound::class, function () {\n                    $this->app->singleton(Timer::class, function () {\n                        return $this->timer;\n                    });\n                    $this->app->singleton(DataTracker::class, function () {\n                        return $this->dataTracker;\n                    });\n                    $this->app->singleton(DataProcessor::class, function () {\n                        return $this->dataProcessor;\n                    });\n                });\n                parent::register();\n            }\n        };\n\n        $app->afterBootstrapping(RegisterProviders::class, function () use ($app, $provider) {\n            $app->register($provider);\n        });\n\n        $app->make(Kernel::class)->bootstrap();\n    }\n\n    /** @test */\n    function loads_profiler_config_file()\n    {\n        $config = $this->app->make('config');\n\n        $this->assertTrue($config->has('profiler'));\n    }\n\n    /** @test */\n    function allows_config_file_to_be_published()\n    {\n        $this->assertArrayHasKey(\n            ServiceProvider::profilerConfigPath(),\n            ServiceProvider::pathsToPublish()\n        );\n    }\n\n    /** @test */\n    function profiler_is_enabled_by_default()\n    {\n        putenv('APP_ENV=test-profiler');\n        $_ENV['APP_ENV'] = 'test-profiler';\n        $this->app = $this->app();\n\n        $config = $this->app->make('config');\n\n        $this->assertTrue($config->get('profiler.enabled'));\n        $this->assertInstanceOf(LaravelProfiler::class, $this->app->make(Profiler::class));\n    }\n\n    /** @test */\n    function profiler_can_be_disabled_in_env_file()\n    {\n        putenv('APP_ENV=test-profiler');\n        putenv('PROFILER_ENABLED=false');\n        $_ENV['APP_ENV'] = 'test-profiler';\n        $_ENV['PROFILER_ENABLED'] = false;\n        $this->app = $this->app();\n\n        $config = $this->app->make('config');\n\n        $this->assertFalse($config->get('profiler.enabled'));\n        $this->assertInstanceOf(DisabledProfiler::class, $this->app->make(Profiler::class));\n    }\n\n    /** @test */\n    function profiler_can_be_disabled_in_config_file_for_specific_environment()\n    {\n        putenv('APP_ENV=local');\n        putenv('PROFILER_ENABLED=true');\n        $_ENV['APP_ENV'] = 'local';\n        $_ENV['PROFILER_ENABLED'] = true;\n        $this->app = $this->appWith(function (Application $app) {\n            $app->make('config')->set('profiler.enabled_overrides', ['local' => false]);\n        });\n\n        $this->assertInstanceOf(DisabledProfiler::class, $this->app->make(Profiler::class));\n    }\n\n    /** @test */\n    function enabled_profiler_tracks_laravel()\n    {\n        $timer = Mockery::spy(Timer::class);\n        $dataTracker = Mockery::spy(DataTracker::class);\n        $dataProcessor = Mockery::spy(DataProcessor::class);\n        $httpRequestHandledListener = Mockery::spy(HttpRequestHandledListener::class);\n        $consoleCommandFinishedListener = Mockery::spy(ConsoleCommandFinishedListener::class);\n\n        $this->app = $this->appBeforeBootstrap();\n        $this->app->instance(HttpRequestHandledListener::class, $httpRequestHandledListener);\n        $this->app->instance(ConsoleCommandFinishedListener::class, $consoleCommandFinishedListener);\n        $this->registerServiceProviderWith($this->app, $timer, $dataTracker, $dataProcessor);\n\n        $this->app->terminate();\n\n        $this->assertInstanceOf(LaravelProfiler::class, $this->app->make(Profiler::class));\n        $this->assertSame($timer, $this->app->make(Timer::class));\n        $this->assertSame($dataTracker, $this->app->make(DataTracker::class));\n        $dataTracker->shouldHaveReceived('track');\n        $dataTracker->shouldHaveReceived('terminate');\n        $this->assertSame($dataProcessor, $this->app->make(DataProcessor::class));\n        $dataProcessor->shouldHaveReceived('process');\n        $httpRequestHandledListener->shouldHaveReceived('listen');\n        $consoleCommandFinishedListener->shouldHaveReceived('listen');\n    }\n\n    /** @test */\n    function disabled_profiler_does_not_track_laravel()\n    {\n        putenv('PROFILER_ENABLED=false');\n        $_ENV['PROFILER_ENABLED'] = false;\n        $timer = Mockery::spy(Timer::class);\n        $dataTracker = Mockery::spy(DataTracker::class);\n        $dataProcessor = Mockery::spy(DataProcessor::class);\n        $httpRequestHandledListener = Mockery::spy(HttpRequestHandledListener::class);\n        $consoleCommandFinishedListener = Mockery::spy(ConsoleCommandFinishedListener::class);\n\n        $this->app = $this->appBeforeBootstrap();\n        $this->app->instance(HttpRequestHandledListener::class, $httpRequestHandledListener);\n        $this->app->instance(ConsoleCommandFinishedListener::class, $consoleCommandFinishedListener);\n        $this->registerServiceProviderWith($this->app, $timer, $dataTracker, $dataProcessor);\n\n        $this->app->terminate();\n\n        $this->assertInstanceOf(DisabledProfiler::class, $this->app->make(Profiler::class));\n        $this->assertSame($timer, $this->app->make(Timer::class));\n        $this->assertSame($dataTracker, $this->app->make(DataTracker::class));\n        $dataTracker->shouldNotHaveReceived('track');\n        $dataTracker->shouldNotHaveReceived('terminate');\n        $this->assertSame($dataProcessor, $this->app->make(DataProcessor::class));\n        $dataProcessor->shouldNotHaveReceived('process');\n        $httpRequestHandledListener->shouldNotHaveReceived('listen');\n        $consoleCommandFinishedListener->shouldNotHaveReceived('listen');\n    }\n\n    /** @test */\n    function enabled_profiler_is_booted_before_all_service_providers_are_booted()\n    {\n        $eventsExecuted = 0;\n        $this->app = $this->appBeforeBootstrap();\n\n        $this->app->afterBootstrapping(RegisterProviders::class, function () use (&$eventsExecuted) {\n            $this->app->register(ServiceProvider::class);\n            $this->assertFalse($this->app->resolved(Timer::class));\n            $eventsExecuted++;\n        });\n\n        $this->app->booting(function () use (&$eventsExecuted) {\n            $this->assertInstanceOf(TimerService::class, $this->app->make(Timer::class));\n            $eventsExecuted++;\n        });\n\n        $this->app->make(Kernel::class)->bootstrap();\n\n        $this->assertEquals(2, $eventsExecuted);\n    }\n\n    /** @test */\n    function disabled_profiler_is_booted_before_all_service_providers_are_booted()\n    {\n        putenv('PROFILER_ENABLED=false');\n        $_ENV['PROFILER_ENABLED'] = false;\n        $eventsExecuted = 0;\n        $this->app = $this->appBeforeBootstrap();\n\n        $this->app->afterBootstrapping(RegisterProviders::class, function () use (&$eventsExecuted) {\n            $this->app->register(ServiceProvider::class);\n            $this->assertFalse($this->app->resolved(Timer::class));\n            $eventsExecuted++;\n        });\n\n        $this->app->booting(function () use (&$eventsExecuted) {\n            $this->assertInstanceOf(NullTimerService::class, $this->app->make(Timer::class));\n            $eventsExecuted++;\n        });\n\n        $this->app->make(Kernel::class)->bootstrap();\n\n        $this->assertEquals(2, $eventsExecuted);\n    }\n\n    /** @test */\n    function enabled_profiler_registers_terminating_callback_after_all_service_providers_are_booted()\n    {\n        $executedBefore = false;\n        $this->app = $this->appBeforeBootstrap();\n\n        $this->app->afterBootstrapping(RegisterProviders::class, function () use (&$order) {\n            $this->app->register(ServiceProvider::class);\n            $this->app->register(new class($this->app) extends \\Illuminate\\Support\\ServiceProvider {\n                public function register() {}\n                public function boot() {\n                    $this->app->terminating(function () {\n                        event('another-executed-before', [new \\stdClass()]);\n                    });\n                }\n            });\n        });\n\n        $this->app->make(Kernel::class)->bootstrap();\n        $this->turnOffProcessors();\n\n        Event::listen('another-executed-before', function () use (&$executedBefore) {\n            $executedBefore = true;\n        });\n\n        Event::listen(Terminating::class, function () use (&$executedBefore) {\n            $this->assertTrue($executedBefore);\n        });\n\n        $this->app->terminate();\n    }\n\n    /**\n     * @return void\n     */\n    protected function tearDown(): void\n    {\n        parent::tearDown();\n\n        putenv('APP_ENV=local');\n        putenv('PROFILER_ENABLED');\n        unset($_ENV['APP_ENV']);\n        unset($_ENV['PROFILER_ENABLED']);\n    }\n}\n"
  },
  {
    "path": "tests/Feature/RunningProfilerTest.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Feature;\n\nuse Mockery;\nuse Exception;\nuse GuzzleHttp\\Client;\nuse GuzzleHttp\\Psr7\\Response;\nuse Illuminate\\Support\\Facades\\Log;\nuse Illuminate\\Foundation\\Application;\nuse JKocik\\Laravel\\Profiler\\Tests\\TestCase;\nuse JKocik\\Laravel\\Profiler\\Services\\ConfigService;\nuse JKocik\\Laravel\\Profiler\\Tests\\Support\\Fixtures\\TrackerA;\nuse JKocik\\Laravel\\Profiler\\Tests\\Support\\Fixtures\\TrackerB;\nuse JKocik\\Laravel\\Profiler\\Processors\\BroadcastingProcessor;\nuse JKocik\\Laravel\\Profiler\\Tests\\Support\\Fixtures\\ProcessorA;\nuse JKocik\\Laravel\\Profiler\\Tests\\Support\\Fixtures\\ProcessorB;\n\nclass RunningProfilerTest extends TestCase\n{\n    /** @test */\n    function collected_data_are_processed_when_laravel_is_terminated()\n    {\n        $this->app = $this->appWith(function (Application $app) {\n            $app->make('config')->set('profiler.trackers', [\n                TrackerA::class,\n                TrackerB::class,\n            ]);\n            $app->make('config')->set('profiler.processors', [\n                ProcessorA::class,\n                ProcessorB::class,\n            ]);\n            $app->singleton(ProcessorA::class, function () {\n               return new ProcessorA();\n            });\n            $app->singleton(ProcessorB::class, function () {\n                return new ProcessorB();\n            });\n        });\n\n        $processorA = $this->app->make(ProcessorA::class);\n        $processorB = $this->app->make(ProcessorB::class);\n\n        $this->assertNotEquals('meta-value', $processorA->meta->get('meta-key'));\n        $this->assertNotEquals('meta-value', $processorB->meta->get('meta-key'));\n        $this->assertNotEquals('data-value', $processorA->data->get('data-key'));\n        $this->assertNotEquals('data-value', $processorB->data->get('data-key'));\n\n        $this->app->terminate();\n\n        $this->assertEquals('meta-value', $processorA->meta->get('meta-key'));\n        $this->assertEquals('meta-value', $processorB->meta->get('meta-key'));\n        $this->assertEquals('data-value', $processorA->data->get('data-key'));\n        $this->assertEquals('data-value', $processorB->data->get('data-key'));\n    }\n\n    /** @test */\n    function collected_data_are_broadcast_by_default()\n    {\n        $config = $this->app->make(ConfigService::class);\n        $client = Mockery::mock(Client::class);\n        $client->shouldReceive('request')->withArgs(function ($arg1, $arg2, $arg3) use ($config) {\n            return $arg1 === 'POST'\n                && $arg2 === $config->serverHttpConnectionUrl()\n                && is_array($arg3['json']['meta'])\n                && is_array($arg3['json']['data']);\n        })->once()->andReturn(new Response());\n\n        $this->app->instance(Client::class, $client);\n\n        $this->app->terminate();\n\n        $this->assertSame($client, $this->app->make(Client::class));\n    }\n\n    /** @test */\n    function collected_data_are_not_processed_for_debugbar()\n    {\n        $client = Mockery::mock(Client::class);\n        $client->shouldNotReceive('request');\n\n        $this->app->instance(Client::class, $client);\n\n        $this->get('_debugbar/assets/javascript');\n    }\n\n    /** @test */\n    function collected_data_are_not_processed_for_telescope()\n    {\n        $client = Mockery::mock(Client::class);\n        $client->shouldNotReceive('request');\n\n        $this->app->instance(Client::class, $client);\n\n        $this->get('telescope/telescope-api/models');\n    }\n\n    /** @test */\n    function processors_exceptions_are_caught_and_logged_if_configured()\n    {\n        $processor = Mockery::mock(ProcessorA::class);\n        $processor->shouldReceive('process')->once();\n\n        $this->app = $this->appWith(function (Application $app) use ($processor) {\n            $app->make('config')->set('profiler.handle_exceptions', 1);\n            $app->make('config')->set('profiler.processors', [\n                BroadcastingProcessor::class,\n                BroadcastingProcessor::class,\n                ProcessorA::class,\n            ]);\n            $app->singleton(ProcessorA::class, function () use ($processor) {\n                return $processor;\n            });\n        });\n\n        Log::shouldReceive('error')\n            ->times(2)\n            ->with(Exception::class);\n\n        $this->app->terminate();\n    }\n\n    /** @test */\n    function processors_exceptions_are_thrown_if_configured()\n    {\n        $processor = Mockery::spy(ProcessorA::class);\n\n        $this->app = $this->appWith(function (Application $app) use ($processor) {\n            $app->make('config')->set('profiler.handle_exceptions', 666);\n            $app->make('config')->set('profiler.processors', [\n                BroadcastingProcessor::class,\n                ProcessorA::class,\n            ]);\n            $app->singleton(ProcessorA::class, function () use ($processor) {\n                return $processor;\n            });\n        });\n\n        try {\n            $this->app->terminate();\n        } catch (Exception $e) {\n            $processor->shouldNotHaveReceived('process');\n            return;\n        }\n\n        $this->fail('Exception should be thrown');\n    }\n\n    /** @test */\n    function processors_exceptions_are_caught_and_not_logged_if_configured()\n    {\n        $processor = Mockery::mock(ProcessorA::class);\n        $processor->shouldReceive('process')->once();\n\n        $this->app = $this->appWith(function (Application $app) use ($processor) {\n            $app->make('config')->set('profiler.handle_exceptions', 0);\n            $app->make('config')->set('profiler.processors', [\n                BroadcastingProcessor::class,\n                BroadcastingProcessor::class,\n                ProcessorA::class,\n            ]);\n            $app->singleton(ProcessorA::class, function () use ($processor) {\n                return $processor;\n            });\n        });\n\n        Log::shouldReceive('error')\n            ->times(0);\n\n        $this->app->terminate();\n    }\n\n    /** @test */\n    function processors_exceptions_are_caught_and_not_logged_if_configured_incorrectly()\n    {\n        $processor = Mockery::mock(ProcessorA::class);\n        $processor->shouldReceive('process')->once();\n\n        $this->app = $this->appWith(function (Application $app) use ($processor) {\n            $app->make('config')->set('profiler.handle_exceptions', -1);\n            $app->make('config')->set('profiler.processors', [\n                BroadcastingProcessor::class,\n                BroadcastingProcessor::class,\n                ProcessorA::class,\n            ]);\n            $app->singleton(ProcessorA::class, function () use ($processor) {\n                return $processor;\n            });\n        });\n\n        Log::shouldReceive('error')\n            ->times(0);\n\n        $this->app->terminate();\n    }\n}\n"
  },
  {
    "path": "tests/Feature/TrackersResetTest.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Feature;\n\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Foundation\\Application;\nuse JKocik\\Laravel\\Profiler\\Tests\\TestCase;\nuse JKocik\\Laravel\\Profiler\\Events\\ResetTrackers;\n\nclass TrackersResetTest extends TestCase\n{\n    /** @test */\n    function trackers_can_be_reset()\n    {\n        $fired = false;\n\n        Event::listen(ResetTrackers::class, function () use (&$fired) {\n            $fired = true;\n        });\n\n        $this->assertFalse($fired);\n\n        profiler_reset();\n\n        $this->assertTrue($fired);\n    }\n\n    /** @test */\n    function profiler_reset_function_can_be_executed_even_profiler_is_disabled()\n    {\n        $this->app = $this->appWith(function (Application $app) {\n            $app->make('config')->set('profiler.enabled', false);\n        });\n\n        $fired = false;\n\n        Event::listen(ResetTrackers::class, function () use (&$fired) {\n            $fired = true;\n        });\n\n        $this->assertFalse($fired);\n\n        profiler_reset();\n\n        $this->assertTrue($fired);\n    }\n}\n"
  },
  {
    "path": "tests/Feature/TrackersTest.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Feature;\n\nuse Mockery;\nuse Illuminate\\Foundation\\Application;\nuse JKocik\\Laravel\\Profiler\\Tests\\TestCase;\nuse JKocik\\Laravel\\Profiler\\Trackers\\AuthTracker;\nuse JKocik\\Laravel\\Profiler\\Trackers\\RedisTracker;\nuse JKocik\\Laravel\\Profiler\\Trackers\\PathsTracker;\nuse JKocik\\Laravel\\Profiler\\Trackers\\RouteTracker;\nuse JKocik\\Laravel\\Profiler\\Trackers\\ViewsTracker;\nuse JKocik\\Laravel\\Profiler\\Trackers\\EventsTracker;\nuse JKocik\\Laravel\\Profiler\\Trackers\\ConfigTracker;\nuse JKocik\\Laravel\\Profiler\\Trackers\\ServerTracker;\nuse JKocik\\Laravel\\Profiler\\Trackers\\ContentTracker;\nuse JKocik\\Laravel\\Profiler\\Trackers\\QueriesTracker;\nuse JKocik\\Laravel\\Profiler\\Trackers\\SessionTracker;\nuse JKocik\\Laravel\\Profiler\\Trackers\\RequestTracker;\nuse JKocik\\Laravel\\Profiler\\Trackers\\ResponseTracker;\nuse JKocik\\Laravel\\Profiler\\Trackers\\BindingsTracker;\nuse JKocik\\Laravel\\Profiler\\Trackers\\ExceptionTracker;\nuse JKocik\\Laravel\\Profiler\\Trackers\\ApplicationTracker;\nuse JKocik\\Laravel\\Profiler\\Trackers\\PerformanceTracker;\nuse JKocik\\Laravel\\Profiler\\Trackers\\ServiceProvidersTracker;\n\nclass TrackersTest extends TestCase\n{\n    /** @test */\n    function application_tracker_is_required()\n    {\n        $defaultTrackers = $this->app->make('config')->get('profiler.trackers');\n\n        $applicationTracker = Mockery::mock(ApplicationTracker::class);\n        $applicationTracker->shouldReceive('terminate')->once();\n        $applicationTracker->shouldReceive('meta')->once()->andReturn(collect());\n        $applicationTracker->shouldReceive('data')->once()->andReturn(collect());\n\n        $this->app = $this->appWith(function (Application $app) use ($applicationTracker) {\n            $app->make('config')->set('profiler.trackers', []);\n            $app->make('config')->set('profiler.processors', []);\n            $app->singleton(ApplicationTracker::class, function () use ($applicationTracker) {\n                return $applicationTracker;\n            });\n        });\n\n        $this->app->terminate();\n\n        $this->assertNotContains(ApplicationTracker::class, $defaultTrackers);\n        $this->assertSame($applicationTracker, $this->app->make(ApplicationTracker::class));\n    }\n\n    /** @test */\n    function request_tracker_is_required()\n    {\n        $defaultTrackers = $this->app->make('config')->get('profiler.trackers');\n\n        $requestTracker = Mockery::mock(RequestTracker::class);\n        $requestTracker->shouldReceive('terminate')->once();\n        $requestTracker->shouldReceive('meta')->once()->andReturn(collect());\n        $requestTracker->shouldReceive('data')->once()->andReturn(collect());\n\n        $this->app = $this->appWith(function (Application $app) use ($requestTracker) {\n            $app->make('config')->set('profiler.trackers', []);\n            $app->make('config')->set('profiler.processors', []);\n            $app->singleton(RequestTracker::class, function () use ($requestTracker) {\n                return $requestTracker;\n            });\n        });\n\n        $this->app->terminate();\n\n        $this->assertNotContains(RequestTracker::class, $defaultTrackers);\n        $this->assertSame($requestTracker, $this->app->make(RequestTracker::class));\n    }\n\n    /** @test */\n    function response_tracker_is_required()\n    {\n        $defaultTrackers = $this->app->make('config')->get('profiler.trackers');\n\n        $responseTracker = Mockery::mock(ResponseTracker::class);\n        $responseTracker->shouldReceive('terminate')->once();\n        $responseTracker->shouldReceive('meta')->once()->andReturn(collect());\n        $responseTracker->shouldReceive('data')->once()->andReturn(collect());\n\n        $this->app = $this->appWith(function (Application $app) use ($responseTracker) {\n            $app->make('config')->set('profiler.trackers', []);\n            $app->make('config')->set('profiler.processors', []);\n            $app->singleton(ResponseTracker::class, function () use ($responseTracker) {\n                return $responseTracker;\n            });\n        });\n\n        $this->app->terminate();\n\n        $this->assertNotContains(ResponseTracker::class, $defaultTrackers);\n        $this->assertSame($responseTracker, $this->app->make(ResponseTracker::class));\n    }\n\n    /** @test */\n    function performance_tracker_is_required()\n    {\n        $defaultTrackers = $this->app->make('config')->get('profiler.trackers');\n\n        $performanceTracker = Mockery::mock(PerformanceTracker::class);\n        $performanceTracker->shouldReceive('terminate')->once();\n        $performanceTracker->shouldReceive('meta')->once()->andReturn(collect());\n        $performanceTracker->shouldReceive('data')->once()->andReturn(collect());\n\n        $this->app = $this->appWith(function (Application $app) use ($performanceTracker) {\n            $app->make('config')->set('profiler.trackers', []);\n            $app->make('config')->set('profiler.processors', []);\n            $app->singleton(PerformanceTracker::class, function () use ($performanceTracker) {\n                return $performanceTracker;\n            });\n        });\n\n        $this->app->terminate();\n\n        $this->assertNotContains(PerformanceTracker::class, $defaultTrackers);\n        $this->assertSame($performanceTracker, $this->app->make(PerformanceTracker::class));\n    }\n\n    /** @test */\n    function paths_tracker_is_enabled_by_default()\n    {\n        $defaultTrackers = $this->app->make('config')->get('profiler.trackers');\n\n        $this->assertContains(PathsTracker::class, $defaultTrackers);\n    }\n\n    /** @test */\n    function service_providers_tracker_is_enabled_by_default()\n    {\n        $defaultTrackers = $this->app->make('config')->get('profiler.trackers');\n\n        $this->assertContains(ServiceProvidersTracker::class, $defaultTrackers);\n    }\n\n    /** @test */\n    function bindings_tracker_is_enabled_by_default()\n    {\n        $defaultTrackers = $this->app->make('config')->get('profiler.trackers');\n\n        $this->assertContains(BindingsTracker::class, $defaultTrackers);\n    }\n\n    /** @test */\n    function config_tracker_is_enabled_by_default()\n    {\n        $defaultTrackers = $this->app->make('config')->get('profiler.trackers');\n\n        $this->assertContains(ConfigTracker::class, $defaultTrackers);\n    }\n\n    /** @test */\n    function session_tracker_is_enabled_by_default()\n    {\n        $defaultTrackers = $this->app->make('config')->get('profiler.trackers');\n\n        $this->assertContains(SessionTracker::class, $defaultTrackers);\n    }\n\n    /** @test */\n    function route_tracker_is_enabled_by_default()\n    {\n        $defaultTrackers = $this->app->make('config')->get('profiler.trackers');\n\n        $this->assertContains(RouteTracker::class, $defaultTrackers);\n    }\n\n    /** @test */\n    function views_tracker_is_enabled_by_default()\n    {\n        $defaultTrackers = $this->app->make('config')->get('profiler.trackers');\n\n        $this->assertContains(ViewsTracker::class, $defaultTrackers);\n    }\n\n    /** @test */\n    function events_tracker_is_enabled_by_default()\n    {\n        $defaultTrackers = $this->app->make('config')->get('profiler.trackers');\n\n        $this->assertContains(EventsTracker::class, $defaultTrackers);\n    }\n\n    /** @test */\n    function queries_tracker_is_enabled_by_default()\n    {\n        $defaultTrackers = $this->app->make('config')->get('profiler.trackers');\n\n        $this->assertContains(QueriesTracker::class, $defaultTrackers);\n    }\n\n    /** @test */\n    function server_tracker_is_enabled_by_default()\n    {\n        $defaultTrackers = $this->app->make('config')->get('profiler.trackers');\n\n        $this->assertContains(ServerTracker::class, $defaultTrackers);\n    }\n\n    /** @test */\n    function content_tracker_is_enabled_by_default()\n    {\n        $defaultTrackers = $this->app->make('config')->get('profiler.trackers');\n\n        $this->assertContains(ContentTracker::class, $defaultTrackers);\n    }\n\n    /** @test */\n    function auth_tracker_is_enabled_by_default()\n    {\n        $defaultTrackers = $this->app->make('config')->get('profiler.trackers');\n\n        $this->assertContains(AuthTracker::class, $defaultTrackers);\n    }\n\n    /** @test */\n    function exception_tracker_is_enabled_by_default()\n    {\n        $defaultTrackers = $this->app->make('config')->get('profiler.trackers');\n\n        $this->assertContains(ExceptionTracker::class, $defaultTrackers);\n    }\n\n    /** @test */\n    function redis_tracker_is_disabled_by_default()\n    {\n        $defaultTrackers = $this->app->make('config')->get('profiler.trackers');\n\n        $this->assertNotContains(RedisTracker::class, $defaultTrackers);\n    }\n}\n"
  },
  {
    "path": "tests/Support/Fixtures/DummyClassA.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Support\\Fixtures;\n\nclass DummyClassA implements DummyContractA\n{\n\n}\n"
  },
  {
    "path": "tests/Support/Fixtures/DummyClassB.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Support\\Fixtures;\n\nclass DummyClassB implements DummyContractB\n{\n\n}\n"
  },
  {
    "path": "tests/Support/Fixtures/DummyCommand.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Support\\Fixtures;\n\nuse Illuminate\\Console\\Command;\n\nclass DummyCommand extends Command\n{\n    /**\n     * @var int\n     */\n    protected $testExitCode;\n\n    /**\n     * DummyCommand constructor.\n     * @param int $testExitCode\n     */\n    public function __construct(int $testExitCode)\n    {\n        parent::__construct();\n\n        $this->testExitCode = $testExitCode;\n    }\n\n    /**\n     * @var string\n     */\n    protected $signature = 'dummy-command {user?} {--number=}';\n\n    /**\n     * @var string\n     */\n    protected $description = 'Display dummy message';\n\n    /**\n     * @return void\n     */\n    public function handle()\n    {\n        $this->comment('Dummy Command Message');\n\n        return $this->testExitCode;\n    }\n}\n"
  },
  {
    "path": "tests/Support/Fixtures/DummyContractA.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Support\\Fixtures;\n\ninterface DummyContractA\n{\n\n}\n"
  },
  {
    "path": "tests/Support/Fixtures/DummyContractB.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Support\\Fixtures;\n\ninterface DummyContractB\n{\n\n}\n"
  },
  {
    "path": "tests/Support/Fixtures/DummyController.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Support\\Fixtures;\n\nuse App\\Http\\Controllers\\Controller;\n\nclass DummyController extends Controller\n{\n    /**\n     * @param DummyFormRequest $request\n     * @return mixed\n     */\n    public function dummyAction(DummyFormRequest $request)\n    {\n        return $request->get('id');\n    }\n}\n"
  },
  {
    "path": "tests/Support/Fixtures/DummyEventA.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Support\\Fixtures;\n\nuse Illuminate\\Queue\\SerializesModels;\n\nclass DummyEventA\n{\n    use SerializesModels;\n}\n"
  },
  {
    "path": "tests/Support/Fixtures/DummyEventB.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Support\\Fixtures;\n\nuse Illuminate\\Support\\Collection;\nuse Illuminate\\Queue\\SerializesModels;\nuse Illuminate\\Database\\Eloquent\\Model;\n\nclass DummyEventB\n{\n    use SerializesModels;\n\n    /**\n     * @var Model\n     */\n    public $user;\n\n    /**\n     * @var Collection\n     */\n    public $usersA;\n\n    /**\n     * @var array\n     */\n    public $usersB;\n\n    /**\n     * @var array\n     */\n    public $dummyClasses;\n\n    /**\n     * @var array\n     */\n    public $dataA;\n\n    /**\n     * @var string\n     */\n    public $dataB;\n\n    /**\n     * DummyEventB constructor.\n     * @param Model $user\n     * @param Collection $usersA\n     * @param array $usersB\n     * @param array $dummyClasses\n     * @param array $dataA\n     * @param string $dataB\n     */\n    public function __construct(\n        Model $user,\n        Collection $usersA,\n        array $usersB,\n        array $dummyClasses,\n        array $dataA,\n        string $dataB\n    ) {\n        $this->user = $user;\n        $this->usersA = $usersA;\n        $this->usersB = $usersB;\n        $this->dummyClasses = $dummyClasses;\n        $this->dataA = $dataA;\n        $this->dataB = $dataB;\n    }\n}\n"
  },
  {
    "path": "tests/Support/Fixtures/DummyException.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Support\\Fixtures;\n\nuse Exception;\n\nclass DummyException extends Exception\n{\n    /**\n     * @return void\n     */\n    public function report()\n    {\n\n    }\n}\n"
  },
  {
    "path": "tests/Support/Fixtures/DummyFormRequest.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Support\\Fixtures;\n\nuse Illuminate\\Foundation\\Http\\FormRequest;\n\nclass DummyFormRequest extends FormRequest\n{\n    /**\n     * @return bool\n     */\n    public function authorize(): bool\n    {\n        return true;\n    }\n\n    /**\n     * @return array\n     */\n    public function rules(): array\n    {\n        return [\n            'id' => 'required',\n        ];\n    }\n}\n"
  },
  {
    "path": "tests/Support/Fixtures/PerformanceProcessor.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Support\\Fixtures;\n\nuse Illuminate\\Support\\Collection;\nuse JKocik\\Laravel\\Profiler\\Contracts\\Processor;\nuse JKocik\\Laravel\\Profiler\\Contracts\\DataTracker;\n\nclass PerformanceProcessor implements Processor\n{\n    /**\n     * @var Collection\n     */\n    public $performance;\n\n    /**\n     * @param DataTracker $dataTracker\n     * @return void\n     */\n    public function process(DataTracker $dataTracker): void\n    {\n        $this->performance = $dataTracker->data()->get('performance');\n    }\n}\n"
  },
  {
    "path": "tests/Support/Fixtures/ProcessorA.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Support\\Fixtures;\n\nuse Illuminate\\Support\\Collection;\nuse JKocik\\Laravel\\Profiler\\Contracts\\Processor;\nuse JKocik\\Laravel\\Profiler\\Contracts\\DataTracker;\n\nclass ProcessorA implements Processor\n{\n    /**\n     * @var Collection\n     */\n    public $meta;\n\n    /**\n     * @var Collection\n     */\n    public $data;\n\n    /**\n     * ProcessorA constructor.\n     */\n    public function __construct()\n    {\n        $this->meta = new Collection();\n        $this->data = new Collection();\n    }\n\n    /**\n     * @param DataTracker $dataTracker\n     * @return void\n     */\n    public function process(DataTracker $dataTracker): void\n    {\n        $this->data = $dataTracker->data();\n        $this->meta = $dataTracker->meta();\n    }\n}\n"
  },
  {
    "path": "tests/Support/Fixtures/ProcessorB.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Support\\Fixtures;\n\nclass ProcessorB extends ProcessorA\n{\n\n}\n"
  },
  {
    "path": "tests/Support/Fixtures/TrackerA.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Support\\Fixtures;\n\nuse Illuminate\\Foundation\\Application;\nuse JKocik\\Laravel\\Profiler\\Trackers\\BaseTracker;\n\nclass TrackerA extends BaseTracker\n{\n    /**\n     * TrackerA constructor.\n     * @param Application $app\n     */\n    public function __construct(Application $app)\n    {\n        parent::__construct($app);\n\n        $this->meta->put('meta-key', 'meta-value');\n    }\n\n    /**\n     * @return void\n     */\n    public function terminate(): void\n    {\n\n    }\n}\n"
  },
  {
    "path": "tests/Support/Fixtures/TrackerB.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Support\\Fixtures;\n\nuse JKocik\\Laravel\\Profiler\\Trackers\\BaseTracker;\n\nclass TrackerB extends BaseTracker\n{\n    /**\n     * @return void\n     */\n    public function terminate(): void\n    {\n        $this->data->put('data-key', 'data-value');\n    }\n}\n"
  },
  {
    "path": "tests/Support/Fixtures/dummy-view-a.blade.php",
    "content": ""
  },
  {
    "path": "tests/Support/Fixtures/dummy-view-b.blade.php",
    "content": ""
  },
  {
    "path": "tests/Support/Framework.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Support;\n\nclass Framework\n{\n    protected const VERSION = TESTS_FRAMEWORK_VERSION;\n\n    /**\n     * @return string\n     */\n    public function version(): string\n    {\n        return static::VERSION;\n    }\n\n    /**\n     * @return string\n     */\n    public function versionWithoutDot(): string\n    {\n        return preg_replace('/\\./', '', $this->version());\n    }\n\n    /**\n     * @return string\n     */\n    public function dir(): string\n    {\n        return \"laravel-{$this->versionWithoutDot()}\";\n    }\n\n    /**\n     * @return string\n     */\n    public function composerPackage(): string\n    {\n        return \"laravel/laravel:{$this->version()}.*\";\n    }\n}\n"
  },
  {
    "path": "tests/Support/PHPMock.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Support;\n\nuse phpmock\\MockBuilder;\nuse phpmock\\environment\\MockEnvironment;\nuse phpmock\\functions\\FixedValueFunction;\n\nclass PHPMock\n{\n    public const TIME = 1234567;\n    public const PHP_VERSION = '7.1.2';\n    public const MEMORY_USAGE = 1222333;\n\n    /**\n     * @return MockEnvironment\n     */\n    public static function phpMock(): MockEnvironment\n    {\n        $phpMock = new MockEnvironment();\n        $phpMock->addMock(self::timeMock()->build());\n        $phpMock->addMock(self::passthruMock()->build());\n        $phpMock->addMock(self::phpVersionMock()->build());\n        $phpMock->addMock(self::memoryUsageMock()->build());\n\n        return $phpMock;\n    }\n\n    /**\n     * @return MockBuilder\n     */\n    protected static function timeMock(): MockBuilder\n    {\n        return (new MockBuilder())\n            ->setNamespace('JKocik\\Laravel\\Profiler\\Trackers')\n            ->setName('time')\n            ->setFunctionProvider(new FixedValueFunction(self::TIME));\n    }\n\n    /**\n     * @return MockBuilder\n     */\n    protected static function passthruMock(): MockBuilder\n    {\n        return (new MockBuilder())\n            ->setNamespace('JKocik\\Laravel\\Profiler\\Console')\n            ->setName('passthru')\n            ->setFunctionProvider(new FixedValueFunction(''));\n    }\n\n    /**\n     * @return MockBuilder\n     */\n    protected static function phpVersionMock(): MockBuilder\n    {\n        return (new MockBuilder())\n            ->setNamespace('JKocik\\Laravel\\Profiler\\Trackers')\n            ->setName('phpversion')\n            ->setFunctionProvider(new FixedValueFunction(self::PHP_VERSION));\n    }\n\n    /**\n     * @return MockBuilder\n     */\n    protected static function memoryUsageMock(): MockBuilder\n    {\n        return (new MockBuilder())\n            ->setNamespace('JKocik\\Laravel\\Profiler\\Services\\Performance')\n            ->setName('memory_get_peak_usage')\n            ->setFunctionProvider(new FixedValueFunction(self::MEMORY_USAGE));\n    }\n}\n"
  },
  {
    "path": "tests/Support/TestListener.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Support;\n\nuse PHPUnit\\Framework\\Test;\nuse PHPUnit\\Framework\\TestListener as BaseTestListener;\nuse PHPUnit\\Framework\\TestListenerDefaultImplementation;\n\nclass TestListener implements BaseTestListener\n{\n    use TestListenerDefaultImplementation;\n\n    /**\n     * @var bool\n     */\n    protected $versionPrinted = false;\n\n    /**\n     * @param Test $test\n     * @return void\n     */\n    public function startTest(Test $test): void\n    {\n        if (! $this->versionPrinted) {\n            $this->printVersion($test);\n        }\n    }\n\n    /**\n     * @return void\n     */\n    protected function printVersion(Test $test): void\n    {\n        fwrite(STDERR, \"APP: {$test->appBeforeBootstrap()->version()}\\n\");\n\n        $this->versionPrinted = true;\n    }\n}\n"
  },
  {
    "path": "tests/TestCase.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests;\n\nuse Closure;\nuse Illuminate\\Foundation\\Application;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Contracts\\Console\\Kernel;\nuse phpmock\\environment\\MockEnvironment;\nuse JKocik\\Laravel\\Profiler\\ServiceProvider;\nuse PHPUnit\\Framework\\TestCase as BaseTestCase;\nuse JKocik\\Laravel\\Profiler\\Tests\\Support\\PHPMock;\nuse JKocik\\Laravel\\Profiler\\Tests\\Support\\Framework;\nuse Illuminate\\Foundation\\Bootstrap\\RegisterProviders;\nuse Mockery\\Adapter\\Phpunit\\MockeryPHPUnitIntegration;\nuse Illuminate\\Foundation\\Testing\\Concerns\\MakesHttpRequests;\nuse Illuminate\\Foundation\\Testing\\Concerns\\InteractsWithSession;\n\nclass TestCase extends BaseTestCase\n{\n    use MakesHttpRequests;\n    use InteractsWithSession;\n    use MockeryPHPUnitIntegration;\n\n    /**\n     * @var Framework\n     */\n    protected static $framework;\n\n    /**\n     * @var Application\n     */\n    protected $app;\n\n    /**\n     * @var string\n     */\n    protected $baseUrl = 'http://localhost';\n\n    /**\n     * @var MockEnvironment\n     */\n    protected $phpMock;\n\n    /**\n     * @return void\n     */\n    public static function setUpBeforeClass(): void\n    {\n        static::$framework = new Framework();\n    }\n\n    /**\n     * @return Application\n     */\n    public function appBeforeBootstrap(): Application\n    {\n        return require __DIR__ . '/../frameworks/' . static::$framework->dir() . '/bootstrap/app.php';\n    }\n\n    /**\n     * @return void\n     */\n    protected function setUp(): void\n    {\n        $this->enablePhpMock();\n\n        $this->app = $this->app();\n    }\n\n    /**\n     * @return void\n     */\n    protected function tearDown(): void\n    {\n        $this->disablePhpMock();\n    }\n\n    /**\n     * @return Application\n     */\n    protected function app(): Application\n    {\n        $app = $this->appBeforeBootstrap();\n\n        $app->afterBootstrapping(RegisterProviders::class, function () use ($app) {\n            $app->register(ServiceProvider::class);\n        });\n\n        $app->make(Kernel::class)->bootstrap();\n\n        return $app;\n    }\n\n    /**\n     * @param Closure $beforeServiceProvider\n     * @return Application\n     */\n    protected function appWith(Closure $beforeServiceProvider): Application\n    {\n        $app = $this->appBeforeBootstrap();\n\n        $app->afterBootstrapping(RegisterProviders::class, function () use ($app, $beforeServiceProvider) {\n            $beforeServiceProvider($app);\n            $app->register(ServiceProvider::class);\n        });\n\n        $app->make(Kernel::class)->bootstrap();\n\n        return $app;\n    }\n\n    /**\n     * @return string\n     */\n    protected function userClass(): string\n    {\n        return $this->app->make('config')->get('auth.providers.users.model');\n    }\n\n    /**\n     * @return object\n     */\n    protected function factoryUser(): object\n    {\n        if (function_exists('factory')) {\n            return factory($this->userClass());\n        }\n\n        return $this->userClass()::factory();\n    }\n\n    /**\n     * @param array $attributes\n     * @return Model\n     */\n    protected function user(array $attributes = []): Model\n    {\n        $userClass = $this->app->make('config')->get('auth.providers.users.model');\n\n        return new $userClass($attributes);\n    }\n\n    /**\n     * @return void\n     */\n    protected function turnOffProcessors(): void\n    {\n        $this->app->make('config')->set('profiler.processors', []);\n    }\n\n    /**\n     * @return void\n     */\n    protected function enablePhpMock(): void\n    {\n        $this->phpMock = PHPMock::phpMock();\n        $this->phpMock->enable();\n    }\n\n    /**\n     * @return void\n     */\n    protected function disablePhpMock(): void\n    {\n        $this->phpMock->disable();\n    }\n\n    /**\n     * @param float $version\n     * @param Closure $callback\n     * @return void\n     */\n    protected function tapLaravelVersionTill(float $version, Closure $callback): void\n    {\n        if (TESTS_FRAMEWORK_VERSION <= $version) {\n            $callback->__invoke();\n        }\n    }\n\n    /**\n     * @param float $version\n     * @param Closure $callback\n     * @return void\n     */\n    protected function tapLaravelVersionFrom(float $version, Closure $callback): void\n    {\n        if (TESTS_FRAMEWORK_VERSION >= $version) {\n            $callback->__invoke();\n        }\n    }\n\n    /**\n     * @param float $versionFrom\n     * @param float $versionTill\n     * @param Closure $callback\n     * @return void\n     */\n    protected function tapLaravelVersionBetween(float $versionFrom, float $versionTill, Closure $callback): void\n    {\n        if (TESTS_FRAMEWORK_VERSION >= $versionFrom && TESTS_FRAMEWORK_VERSION <= $versionTill) {\n            $callback->__invoke();\n        }\n    }\n}\n"
  },
  {
    "path": "tests/Unit/LaravelExecution/ConsoleFinishedRequestTest.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Unit\\LaravelExecution;\n\nuse Mockery;\nuse JKocik\\Laravel\\Profiler\\Tests\\TestCase;\nuse Symfony\\Component\\Console\\Input\\InputInterface;\nuse JKocik\\Laravel\\Profiler\\LaravelExecution\\ConsoleFinishedRequest;\n\nclass ConsoleFinishedRequestTest extends TestCase\n{\n    /** @test */\n    function allows_command_to_be_null()\n    {\n        $input = Mockery::mock(InputInterface::class);\n\n        $consoleFinishedRequest = new ConsoleFinishedRequest(null, $input);\n\n        $this->assertNull($consoleFinishedRequest->meta()->get('path'));\n    }\n}\n"
  },
  {
    "path": "tests/Unit/LaravelExecution/ConsoleStartingRequestTest.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Unit\\LaravelExecution;\n\nuse JKocik\\Laravel\\Profiler\\Tests\\TestCase;\nuse JKocik\\Laravel\\Profiler\\LaravelExecution\\ConsoleStartingRequest;\n\nclass ConsoleStartingRequestTest extends TestCase\n{\n    /** @test */\n    function returns_meta_and_data()\n    {\n        $consoleStartingRequest = new ConsoleStartingRequest();\n\n        $this->assertEquals('command-starting', $consoleStartingRequest->meta()->get('type'));\n        $this->assertCount(0, $consoleStartingRequest->data());\n    }\n}\n"
  },
  {
    "path": "tests/Unit/LaravelExecution/ConsoleStartingResponseTest.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Unit\\LaravelExecution;\n\nuse JKocik\\Laravel\\Profiler\\Tests\\TestCase;\nuse JKocik\\Laravel\\Profiler\\LaravelExecution\\ConsoleStartingResponse;\n\nclass ConsoleStartingResponseTest extends TestCase\n{\n    /** @test */\n    function returns_meta_and_data()\n    {\n        $consoleStartingResponse = new ConsoleStartingResponse();\n\n        $this->assertNull($consoleStartingResponse->meta()->get('type'));\n        $this->assertCount(0, $consoleStartingResponse->data());\n    }\n}\n"
  },
  {
    "path": "tests/Unit/Services/ConfigServiceTest.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Unit\\Services;\n\nuse Illuminate\\Foundation\\Application;\nuse JKocik\\Laravel\\Profiler\\Tests\\TestCase;\nuse JKocik\\Laravel\\Profiler\\Services\\LogService;\nuse JKocik\\Laravel\\Profiler\\Services\\ConfigService;\nuse JKocik\\Laravel\\Profiler\\Tests\\Support\\Fixtures\\TrackerA;\nuse JKocik\\Laravel\\Profiler\\Tests\\Support\\Fixtures\\TrackerB;\nuse JKocik\\Laravel\\Profiler\\Tests\\Support\\Fixtures\\ProcessorA;\nuse JKocik\\Laravel\\Profiler\\Tests\\Support\\Fixtures\\ProcessorB;\n\nclass ConfigServiceTest extends TestCase\n{\n    /** @test */\n    function returns_trackers()\n    {\n        $this->app = $this->appWith(function (Application $app) {\n            $app->make('config')->set('profiler.trackers', [\n                TrackerA::class,\n                TrackerB::class,\n            ]);\n        });\n\n        $trackers = $this->app->make(ConfigService::class)->trackers();\n\n        $this->assertTrue($trackers->contains(TrackerA::class));\n        $this->assertTrue($trackers->contains(TrackerB::class));\n    }\n\n    /** @test */\n    function returns_processors()\n    {\n        $this->app = $this->appWith(function (Application $app) {\n            $app->make('config')->set('profiler.processors', [\n                ProcessorA::class,\n                ProcessorB::class,\n            ]);\n        });\n\n        $processors = $this->app->make(ConfigService::class)->processors();\n\n        $this->assertTrue($processors->contains(ProcessorA::class));\n        $this->assertTrue($processors->contains(ProcessorB::class));\n    }\n\n    /** @test */\n    function returns_server_http_connection_url()\n    {\n        $url = $this->app->make(ConfigService::class)->serverHttpConnectionUrl();\n\n        $this->assertEquals('http://localhost:8099', $url);\n    }\n\n    /** @test */\n    function returns_server_http_port()\n    {\n        $port = $this->app->make(ConfigService::class)->serverHttpPort();\n\n        $this->assertEquals('8099', $port);\n    }\n\n    /** @test */\n    function returns_server_sockets_port()\n    {\n        $port = $this->app->make(ConfigService::class)->serverSocketsPort();\n\n        $this->assertEquals('1901', $port);\n    }\n\n    /** @test */\n    function returns_handle_exceptions()\n    {\n        $handleDefault = $this->app->make(ConfigService::class)->handleExceptions(\n            LogService::HANDLE_EXCEPTIONS_LOG\n        );\n\n        $this->assertTrue($handleDefault);\n    }\n}\n"
  },
  {
    "path": "tests/Unit/Services/HelpersTest.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Unit\\Services;\n\nuse JKocik\\Laravel\\Profiler\\Tests\\TestCase;\n\nclass HelpersTest extends TestCase\n{\n    /** @test */\n    function helpers_functions_can_not_brake_application_by_second_definition_in_global_namespace()\n    {\n        require __DIR__ . '/../../../src/Services/helpers.php';\n\n        $this->assertTrue(true);\n    }\n}\n"
  },
  {
    "path": "tests/Unit/Services/ParamsServiceTest.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Unit\\Services;\n\nuse JKocik\\Laravel\\Profiler\\Tests\\TestCase;\nuse JKocik\\Laravel\\Profiler\\Services\\ParamsService;\nuse JKocik\\Laravel\\Profiler\\Tests\\Support\\Fixtures\\DummyClassA;\nuse JKocik\\Laravel\\Profiler\\Tests\\Support\\Fixtures\\DummyClassB;\n\nclass ParamsServiceTest extends TestCase\n{\n    /** @test */\n    function returns_value_of_primitive_param_type()\n    {\n        $paramsService = $this->app->make(ParamsService::class);\n\n        $this->assertEquals(1, $paramsService->resolve(1));\n        $this->assertEquals('something', $paramsService->resolve('something'));\n        $this->assertEquals(['a', 'b'], $paramsService->resolve(['a', 'b']));\n        $this->assertEquals(true, $paramsService->resolve(true));\n        $this->assertEquals(false, $paramsService->resolve(false));\n    }\n\n    /** @test */\n    function returns_array_of_object_param_if_is_available()\n    {\n        $paramsService = $this->app->make(ParamsService::class);\n        $user = $this->user(['email' => 'a@example.com']);\n\n        $this->assertEquals($user->toArray(), $paramsService->resolve($user));\n    }\n\n    /** @test */\n    function returns_class_name_of_object_param_if_array_is_not_available()\n    {\n        $paramsService = $this->app->make(ParamsService::class);\n        $dummyClassA = new DummyClassA();\n\n        $this->assertEquals(DummyClassA::class, $paramsService->resolve($dummyClassA));\n    }\n\n    /** @test */\n    function can_resolve_array_of_objects()\n    {\n        $paramsService = $this->app->make(ParamsService::class);\n        $dummyClassA = new DummyClassA();\n        $dummyClassB = new DummyClassB();\n\n        $this->assertEquals([\n            DummyClassA::class,\n            DummyClassB::class,\n        ], $paramsService->resolve([$dummyClassA, $dummyClassB]));\n    }\n}\n"
  },
  {
    "path": "tests/Unit/Services/Performance/TimerServiceTest.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Unit\\Services\\Performance;\n\nuse Mockery;\nuse Illuminate\\Support\\Facades\\Log;\nuse Illuminate\\Foundation\\Application;\nuse JKocik\\Laravel\\Profiler\\Tests\\TestCase;\nuse JKocik\\Laravel\\Profiler\\Contracts\\Timer;\nuse JKocik\\Laravel\\Profiler\\Services\\Performance\\TimerService;\nuse JKocik\\Laravel\\Profiler\\Services\\Performance\\TimerException;\nuse JKocik\\Laravel\\Profiler\\Services\\Performance\\NullTimerService;\n\nclass TimerServiceTest extends TestCase\n{\n    /** @test */\n    function counts_execution_time_in_milliseconds()\n    {\n        $timer = $this->app->make(TimerService::class);\n\n        $timer->start('testA');\n        $timer->finish('testA');\n\n        $timer->start('testB');\n        usleep(10 * 1000);\n        $timer->finish('testB');\n\n        $timer->start('testC');\n        usleep(200 * 1000);\n        $timer->finish('testC');\n\n        $this->assertGreaterThanOrEqual(0, $timer->milliseconds('testA'));\n        $this->assertGreaterThanOrEqual(10, $timer->milliseconds('testB'));\n        $this->assertGreaterThanOrEqual(200, $timer->milliseconds('testC'));\n    }\n\n    /** @test */\n    function counts_laravel_execution_time()\n    {\n        $appL = Mockery::mock(Application::class);\n        $appL->shouldReceive('environment')->with('testing')->andReturn(false)->once();\n\n        $appT = Mockery::mock(Application::class);\n        $appT->shouldReceive('environment')->with('testing')->andReturn(true)->once();\n\n        $timerA1 = new TimerService($appL);\n        $timerB1 = new TimerService($appT);\n        $timerA2 = new TimerService($appL);\n        $timerB2 = new TimerService($appT);\n        $millisecondsWithLaravelStartDefined = \\microtime(true) * 1000;\n\n        $timerA1->startLaravel();\n        $timerA1->finishLaravel();\n        $timerB1->startLaravel();\n        $timerB1->finishLaravel();\n\n        define('LARAVEL_START', 0);\n        $timerA2->startLaravel();\n        $timerA2->finishLaravel();\n        $timerB2->startLaravel();\n        $timerB2->finishLaravel();\n\n        $this->assertLessThan($millisecondsWithLaravelStartDefined, $timerA1->milliseconds('laravel'));\n        $this->assertGreaterThanOrEqual($millisecondsWithLaravelStartDefined, $timerA2->milliseconds('laravel'));\n        $this->assertLessThan($millisecondsWithLaravelStartDefined, $timerB1->milliseconds('laravel'));\n        $this->assertLessThan($millisecondsWithLaravelStartDefined, $timerB2->milliseconds('laravel'));\n    }\n\n    /** @test */\n    function returns_all_finished_times()\n    {\n        $timer = $this->app->make(TimerService::class);\n\n        $timer->start('testA');\n        $timer->finish('testA');\n\n        $timer->start('testB');\n        $timer->finish('testB');\n\n        $timer->start('testC');\n\n        $this->assertArrayHasKey('testA', $timer->all());\n        $this->assertArrayHasKey('testB', $timer->all());\n        $this->assertArrayNotHasKey('testC', $timer->all());\n        $this->assertEquals($timer->milliseconds('testA'), $timer->all()['testA']);\n        $this->assertEquals($timer->milliseconds('testB'), $timer->all()['testB']);\n    }\n\n    /** @test */\n    function returns_negative_value_when_timer_for_specific_label_is_not_completed()\n    {\n        $timer = $this->app->make(TimerService::class);\n\n        $timer->start('testA');\n\n        $this->assertEquals(-1, $timer->milliseconds('testA'));\n    }\n\n    /** @test */\n    function allows_custom_timer_for_application_developers_but_keep_it_in_different_namespace()\n    {\n        $timer = $this->app->make(TimerService::class);\n\n        $timer->startCustom('testA');\n        $timer->finishCustom('testA');\n\n        $this->assertGreaterThan(0, $timer->millisecondsCustom('testA'));\n        $this->assertNotEquals($timer->milliseconds('testA'), $timer->millisecondsCustom('testA'));\n    }\n\n    /** @test */\n    function returns_empty_values_for_null_timer()\n    {\n        $timer = new NullTimerService();\n\n        $timer->startCustom('testA');\n        $timer->finishCustom('testA');\n\n        $this->assertEquals(-1, $timer->millisecondsCustom('testA'));\n    }\n\n    /** @test */\n    function the_same_custom_timer_can_not_be_started_more_than_once()\n    {\n        try {\n            $timer = $this->app->make(TimerService::class);\n\n            $timer->startCustom('testA');\n            $timer->startCustom('testA');\n        } catch (TimerException $e) {\n            $this->assertTrue(true);\n            return;\n        }\n\n        $this->fail('TimerException should be thrown');\n    }\n\n    /** @test */\n    function the_same_custom_timer_can_not_be_finished_more_than_once()\n    {\n        try {\n            $timer = $this->app->make(TimerService::class);\n\n            $timer->startCustom('testA');\n            $timer->finishCustom('testA');\n            $timer->finishCustom('testA');\n        } catch (TimerException $e) {\n            $this->assertTrue(true);\n            return;\n        }\n\n        $this->fail('TimerException should be thrown');\n    }\n\n    /** @test */\n    function custom_timer_can_not_be_finished_if_is_not_started_before()\n    {\n        try {\n            $timer = $this->app->make(TimerService::class);\n\n            $timer->finishCustom('testA');\n        } catch (TimerException $e) {\n            $this->assertTrue(true);\n            return;\n        }\n\n        $this->fail('TimerException should be thrown');\n    }\n\n    /** @test */\n    function custom_timer_is_used_by_helper_functions()\n    {\n        profiler_start('testA');\n        profiler_finish('testA');\n\n        $timer = $this->app->make(Timer::class);\n\n        $this->assertGreaterThan(0, $timer->millisecondsCustom('testA'));\n    }\n\n    /** @test */\n    function custom_timer_functions_exceptions_are_caught_and_logged_if_configured()\n    {\n        $this->app = $this->appWith(function (Application $app) {\n            $app->make('config')->set('profiler.handle_exceptions', 1);\n        });\n\n        Log::shouldReceive('error')\n            ->times(2)\n            ->with(TimerException::class);\n\n        profiler_start('testA');\n        profiler_start('testA');\n        profiler_finish('testB');\n    }\n\n    /** @test */\n    function custom_timer_functions_exceptions_are_thrown_if_configured()\n    {\n        $this->app = $this->appWith(function (Application $app) {\n            $app->make('config')->set('profiler.handle_exceptions', 666);\n        });\n\n        Log::shouldReceive('error')\n            ->times(0)\n            ->with(TimerException::class);\n\n        try {\n            profiler_start('testA');\n            profiler_start('testA');\n        } catch (TimerException $e) {\n            $this->assertTrue(true);\n            return;\n        }\n\n        $this->fail('TimerException should be thrown');\n    }\n\n    /** @test */\n    function custom_timer_functions_exceptions_are_caught_and_not_logged_if_configured()\n    {\n        $this->app = $this->appWith(function (Application $app) {\n            $app->make('config')->set('profiler.handle_exceptions', 0);\n        });\n\n        Log::shouldReceive('error')\n            ->times(0);\n\n        profiler_start('testA');\n        profiler_start('testA');\n        profiler_finish('testB');\n    }\n\n    /** @test */\n    function custom_timer_functions_exceptions_are_caught_and_not_logged_if_configured_incorrectly()\n    {\n        $this->app = $this->appWith(function (Application $app) {\n            $app->make('config')->set('profiler.handle_exceptions', -1);\n        });\n\n        Log::shouldReceive('error')\n            ->times(0);\n\n        profiler_start('testA');\n        profiler_start('testA');\n        profiler_finish('testB');\n    }\n}\n"
  },
  {
    "path": "tests/Unit/Trackers/ApplicationTrackerTest.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Unit\\Trackers;\n\nuse Mockery;\nuse Illuminate\\Foundation\\Application;\nuse JKocik\\Laravel\\Profiler\\Tests\\TestCase;\nuse JKocik\\Laravel\\Profiler\\Tests\\Support\\PHPMock;\nuse JKocik\\Laravel\\Profiler\\Trackers\\ApplicationTracker;\n\nclass ApplicationTrackerTest extends TestCase\n{\n    /** @test */\n    function has_execution_at()\n    {\n        $tracker = $this->app->make(ApplicationTracker::class);\n\n        $tracker->terminate();\n\n        $this->assertTrue($tracker->meta()->has('execution_at'));\n        $this->assertEquals(PHPMock::TIME, $tracker->meta()->get('execution_at'));\n    }\n\n    /** @test */\n    function has_profiler_single_execution_id()\n    {\n        $tracker = $this->app->make(ApplicationTracker::class);\n\n        $tracker->terminate();\n\n        $this->assertTrue($tracker->meta()->has('id'));\n        $this->assertRegExp('/^[a-z0-9]{32}$/', $tracker->meta()->get('id'));\n    }\n\n    /** @test */\n    function profiler_single_execution_id_is_unique()\n    {\n        $tracker = $this->app->make(ApplicationTracker::class);\n\n        $tracker->terminate();\n        $firstId = $tracker->meta()->get('id');\n\n        $tracker->terminate();\n        $secondId = $tracker->meta()->get('id');\n\n        $this->assertNotEquals($firstId, $secondId);\n    }\n\n    /** @test */\n    function has_laravel_version()\n    {\n        $tracker = $this->app->make(ApplicationTracker::class);\n\n        $tracker->terminate();\n\n        $this->assertTrue($tracker->meta()->has('laravel_version'));\n        $this->assertEquals($this->app->version(), $tracker->meta()->get('laravel_version'));\n    }\n\n    /** @test */\n    function has_php_version()\n    {\n        $tracker = $this->app->make(ApplicationTracker::class);\n\n        $tracker->terminate();\n\n        $this->assertTrue($tracker->meta()->has('php_version'));\n        $this->assertEquals(PHPMock::PHP_VERSION, $tracker->meta()->get('php_version'));\n    }\n\n    /** @test */\n    function has_env()\n    {\n        $tracker = $this->app->make(ApplicationTracker::class);\n\n        $tracker->terminate();\n\n        $this->assertTrue($tracker->meta()->has('env'));\n        $this->assertEquals('local', $tracker->meta()->get('env'));\n    }\n\n    /** @test */\n    function has_is_running_in_console()\n    {\n        $app = Mockery::mock(Application::class)->shouldIgnoreMissing();\n        $app->shouldReceive('runningInConsole')->once()->andReturn(false);\n        $this->app->instance(Application::class, $app);\n\n        $tracker = $this->app->make(ApplicationTracker::class);\n\n        $tracker->terminate();\n\n        $this->assertTrue($tracker->meta()->has('is_running_in_console'));\n        $this->assertFalse($tracker->meta()->get('is_running_in_console'));\n    }\n\n    /** @test */\n    function has_locale()\n    {\n        $tracker = $this->app->make(ApplicationTracker::class);\n\n        $tracker->terminate();\n        $application = $tracker->data()->get('application');\n\n        $this->assertTrue($application->has('locale'));\n        $this->assertEquals($this->app->getLocale(), $application->get('locale'));\n    }\n\n    /** @test */\n    function has_configuration_is_cached()\n    {\n        $app = Mockery::mock(Application::class)->shouldIgnoreMissing();\n        $app->shouldReceive('configurationIsCached')->once()->andReturn(true);\n        $this->app->instance(Application::class, $app);\n\n        $tracker = $this->app->make(ApplicationTracker::class);\n\n        $tracker->terminate();\n        $application = $tracker->data()->get('application');\n\n        $this->assertTrue($application->has('configuration_is_cached'));\n        $this->assertTrue($application->get('configuration_is_cached'));\n    }\n\n    /** @test */\n    function has_routes_are_cached()\n    {\n        $app = Mockery::mock(Application::class)->shouldIgnoreMissing();\n        $app->shouldReceive('routesAreCached')->once()->andReturn(true);\n        $this->app->instance(Application::class, $app);\n\n        $tracker = $this->app->make(ApplicationTracker::class);\n\n        $tracker->terminate();\n        $application = $tracker->data()->get('application');\n\n        $this->assertTrue($application->has('routes_are_cached'));\n        $this->assertTrue($application->get('routes_are_cached'));\n    }\n\n    /** @test */\n    function has_is_down_for_maintenance()\n    {\n        $app = Mockery::mock(Application::class)->shouldIgnoreMissing();\n        $app->shouldReceive('isDownForMaintenance')->once()->andReturn(true);\n        $this->app->instance(Application::class, $app);\n\n        $tracker = $this->app->make(ApplicationTracker::class);\n\n        $tracker->terminate();\n        $application = $tracker->data()->get('application');\n\n        $this->assertTrue($application->has('is_down_for_maintenance'));\n        $this->assertTrue($application->get('is_down_for_maintenance'));\n    }\n\n    /** @test */\n    function has_should_skip_middleware()\n    {\n        $app = Mockery::mock(Application::class)->shouldIgnoreMissing();\n        $app->shouldReceive('shouldSkipMiddleware')->once()->andReturn(true);\n        $this->app->instance(Application::class, $app);\n\n        $tracker = $this->app->make(ApplicationTracker::class);\n\n        $tracker->terminate();\n        $application = $tracker->data()->get('application');\n\n        $this->assertTrue($application->has('should_skip_middleware'));\n        $this->assertTrue($application->get('should_skip_middleware'));\n    }\n}\n"
  },
  {
    "path": "tests/Unit/Trackers/AuthTrackerTest.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Unit\\Trackers;\n\nuse Illuminate\\Support\\Facades\\Auth;\nuse Illuminate\\Support\\Facades\\Artisan;\nuse JKocik\\Laravel\\Profiler\\Tests\\TestCase;\nuse JKocik\\Laravel\\Profiler\\Trackers\\AuthTracker;\n\nclass AuthTrackerTest extends TestCase\n{\n    /**\n     * @return void\n     */\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        Artisan::call('migrate');\n    }\n\n    /**\n     * @return void\n     */\n    protected function tearDown(): void\n    {\n        parent::tearDown();\n\n        Artisan::call('migrate:rollback');\n    }\n\n    /** @test */\n    function has_auth_user()\n    {\n        $tracker = $this->app->make(AuthTracker::class);\n\n        $user = $this->factoryUser()->create(['email' => 'user@example.com']);\n        Auth::login($user);\n\n        $tracker->terminate();\n        $auth = $tracker->data()->get('auth');\n\n        $this->assertEquals($user->email, $auth->email);\n    }\n\n    /** @test */\n    function has_auth_user_even_user_is_logging_out()\n    {\n        $tracker = $this->app->make(AuthTracker::class);\n\n        $user = $this->factoryUser()->create([\n            'email' => 'login.me@example.com',\n        ]);\n        Auth::login($user);\n        Auth::logout();\n\n        $tracker->terminate();\n        $auth = $tracker->data()->get('auth');\n\n        $this->assertEquals($user->email, $auth->email);\n    }\n\n    /** @test */\n    function has_null_auth_user_if_user_is_not_logged_in()\n    {\n        $tracker = $this->app->make(AuthTracker::class);\n\n        $tracker->terminate();\n        $auth = $tracker->data()->get('auth');\n\n        $this->assertNull($auth);\n    }\n}\n"
  },
  {
    "path": "tests/Unit/Trackers/BindingsTrackerTest.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Unit\\Trackers;\n\nuse JKocik\\Laravel\\Profiler\\Tests\\TestCase;\nuse JKocik\\Laravel\\Profiler\\Trackers\\BindingsTracker;\nuse JKocik\\Laravel\\Profiler\\Tests\\Support\\Fixtures\\DummyClassA;\nuse JKocik\\Laravel\\Profiler\\Tests\\Support\\Fixtures\\DummyClassB;\nuse JKocik\\Laravel\\Profiler\\Tests\\Support\\Fixtures\\DummyContractA;\nuse JKocik\\Laravel\\Profiler\\Tests\\Support\\Fixtures\\DummyContractB;\n\nclass BindingsTrackerTest extends TestCase\n{\n    /** @test */\n    function has_container_bindings_abstracts()\n    {\n        $tracker = $this->app->make(BindingsTracker::class);\n\n        $tracker->terminate();\n        $bindings = $tracker->data()->get('bindings');\n\n        $this->assertNotNull($bindings);\n        $this->assertCount(count($bindings), $this->app->getBindings());\n        $this->assertSame(0, $bindings->keys()[0]);\n        $this->assertContains($bindings->first()['abstract'], array_keys($this->app->getBindings()));\n    }\n\n    /** @test */\n    function tracks_how_container_resolves_bindings()\n    {\n        $this->app->bind(DummyContractA::class, DummyClassA::class);\n        $this->app->bind(DummyContractB::class, DummyClassB::class);\n        $this->app->make(DummyContractB::class);\n        $tracker = $this->app->make(BindingsTracker::class);\n\n        $tracker->terminate();\n        $bindings = $tracker->data()->get('bindings');\n\n        $this->assertNull($bindings->where('abstract', DummyContractA::class)->first()['resolved']);\n        $this->assertEquals(DummyClassB::class, $bindings->where('abstract', DummyContractB::class)->first()['resolved']);\n    }\n}\n"
  },
  {
    "path": "tests/Unit/Trackers/ConfigTrackerTest.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Unit\\Trackers;\n\nuse JKocik\\Laravel\\Profiler\\Tests\\TestCase;\nuse JKocik\\Laravel\\Profiler\\Trackers\\ConfigTracker;\n\nclass ConfigTrackerTest extends TestCase\n{\n    /** @test */\n    function has_config_data()\n    {\n        $tracker = $this->app->make(ConfigTracker::class);\n\n        $tracker->terminate();\n        $config = $tracker->data()->get('config');\n\n        $this->assertNotNull($config);\n        $this->assertEquals(collect($this->app->make('config')->all())->keys(), $config->keys());\n    }\n\n    /** @test */\n    function has_hidden_secret_config_data()\n    {\n        config()->set('my-config.password', '1');\n        config()->set('my-config.next-config-level.password', '12');\n        config()->set('my-config.next-config-level.even-deeper.password', '123');\n        config()->set('my-config.PASSWORD', '1234');\n        config()->set('my-config.key', '12345');\n        config()->set('my-config.secret', '123456');\n        config()->set('my-config.value_password', '1234567');\n        config()->set('my-config.some_password_value', '12345678');\n        config()->set('my-config.password-value', '123456789');\n\n        $tracker = $this->app->make(ConfigTracker::class);\n\n        $tracker->terminate();\n        $config = $tracker->data()->get('config')->toArray();\n\n        $this->assertEquals('*', $config['my-config']['password']);\n        $this->assertEquals('**', $config['my-config']['next-config-level']['password']);\n        $this->assertEquals('***', $config['my-config']['next-config-level']['even-deeper']['password']);\n        $this->assertEquals('****', $config['my-config']['PASSWORD']);\n        $this->assertEquals('*****', $config['my-config']['key']);\n        $this->assertEquals('******', $config['my-config']['secret']);\n        $this->assertEquals('1234567', $config['my-config']['value_password']);\n        $this->assertEquals('12345678', $config['my-config']['some_password_value']);\n        $this->assertEquals('123456789', $config['my-config']['password-value']);\n    }\n}\n"
  },
  {
    "path": "tests/Unit/Trackers/ContentTrackerTest.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Unit\\Trackers;\n\nuse Mockery;\nuse JKocik\\Laravel\\Profiler\\Tests\\TestCase;\nuse JKocik\\Laravel\\Profiler\\Trackers\\ContentTracker;\nuse JKocik\\Laravel\\Profiler\\Contracts\\ExecutionData;\nuse JKocik\\Laravel\\Profiler\\Contracts\\ExecutionContent;\n\nclass ContentTrackerTest extends TestCase\n{\n    /** @test */\n    function has_content_meta()\n    {\n        $content = Mockery::mock(ExecutionContent::class)->shouldIgnoreMissing();\n        $content->shouldReceive('meta')->once()->andReturn(collect([\n            'key-a' => 'val-a',\n            'key-b' => 'val-b',\n            'key-c' => 'val-c',\n        ]));\n        $content->shouldReceive('data')->andReturn(collect());\n        $this->app->make(ExecutionData::class)->setContent($content);\n\n        $tracker = $this->app->make(ContentTracker::class);\n        $tracker->terminate();\n\n        $this->assertEquals('val-a', $tracker->meta()->get('key-a'));\n        $this->assertEquals('val-b', $tracker->meta()->get('key-b'));\n        $this->assertEquals('val-c', $tracker->meta()->get('key-c'));\n    }\n\n    /** @test */\n    function has_content_data()\n    {\n        $content = Mockery::mock(ExecutionContent::class)->shouldIgnoreMissing();\n        $content->shouldReceive('data')->once()->andReturn(collect([\n            'content' => '<html><body></body></html>',\n        ]));\n        $this->app->make(ExecutionData::class)->setContent($content);\n\n        $tracker = $this->app->make(ContentTracker::class);\n        $tracker->terminate();\n\n        $this->assertEquals('<html><body></body></html>', $tracker->data()->get('content'));\n    }\n}\n"
  },
  {
    "path": "tests/Unit/Trackers/EventsTrackerTest.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Unit\\Trackers;\n\nuse Exception;\nuse Illuminate\\Events\\Dispatcher;\nuse JKocik\\Laravel\\Profiler\\Tests\\TestCase;\nuse JKocik\\Laravel\\Profiler\\Events\\Tracking;\nuse JKocik\\Laravel\\Profiler\\Events\\Terminating;\nuse JKocik\\Laravel\\Profiler\\Events\\ProfilerBound;\nuse JKocik\\Laravel\\Profiler\\Events\\ResetTrackers;\nuse JKocik\\Laravel\\Profiler\\Trackers\\EventsTracker;\nuse JKocik\\Laravel\\Profiler\\Events\\ExceptionHandling;\nuse JKocik\\Laravel\\Profiler\\Tests\\Support\\Fixtures\\DummyClassA;\nuse JKocik\\Laravel\\Profiler\\Tests\\Support\\Fixtures\\DummyClassB;\nuse JKocik\\Laravel\\Profiler\\Tests\\Support\\Fixtures\\DummyEventA;\nuse JKocik\\Laravel\\Profiler\\Tests\\Support\\Fixtures\\DummyEventB;\nuse JKocik\\Laravel\\Profiler\\Tests\\Support\\Fixtures\\DummyListenerA;\n\nclass EventsTrackerTest extends TestCase\n{\n    /** @test */\n    function has_fired_events()\n    {\n        $tracker = $this->app->make(EventsTracker::class);\n        $dispatcher = $this->app->make(Dispatcher::class);\n\n        $this->tapLaravelVersionTill(5.3, function () use ($dispatcher) {\n            $dispatcher->fire('testing: tracker', [new \\stdClass()]);\n        });\n        $this->tapLaravelVersionFrom(5.4, function () use ($dispatcher) {\n            $dispatcher->dispatch('testing: tracker', [new \\stdClass()]);\n        });\n        event(new DummyEventA());\n\n        $tracker->terminate();\n        $events = $tracker->data()->get('events');\n\n        $this->assertNotNull($events);\n        $this->assertTrue($events->contains('name', 'testing: tracker'));\n        $this->assertTrue($events->contains('name', DummyEventA::class));\n        $this->assertEquals(2, $tracker->meta()->get('events_count'));\n    }\n\n    /** @test */\n    function has_data_of_fired_events()\n    {\n        $this->app->make('config')->set('profiler.data.events', true);\n        $this->app->make('config')->set('profiler.group.events', false);\n\n        $tracker = $this->app->make(EventsTracker::class);\n\n        $user = $this->user(['email' => 'a@example.com']);\n        $usersA = collect([$this->user(['email' => 'b@example.com']), $this->user(['email' => 'c@example.com'])]);\n        $usersB = [$this->user(['email' => 'd@example.com']), $this->user(['email' => collect(['email' => 'e@example.com'])])];\n        $dummyClasses = [new DummyClassA(), new DummyClassB()];\n        $dataA = ['a' => 1, 'c' => 2];\n        $dataB = 'c';\n\n        event(new DummyEventB($user, $usersA, $usersB, $dummyClasses, $dataA, $dataB));\n\n        $tracker->terminate();\n        $events = $tracker->data()->get('events');\n        $eventB = $events->where('name', DummyEventB::class)->first();\n\n        $this->assertEquals(['email' => 'a@example.com'], $eventB['data']['user']);\n        $this->assertEquals([\n            0 => ['email' => 'b@example.com'],\n            1 => ['email' => 'c@example.com'],\n        ], $eventB['data']['usersA']);\n        $this->assertEquals([\n            0 => ['email' => 'd@example.com'],\n            1 => ['email' => ['email' => 'e@example.com']],\n        ], $eventB['data']['usersB']);\n        $this->assertEquals([DummyClassA::class, DummyClassB::class], $eventB['data']['dummyClasses']);\n        $this->assertEquals(['a' => 1, 'c' => 2], $eventB['data']['dataA']);\n        $this->assertEquals('c', $eventB['data']['dataB']);\n    }\n\n    /** @test */\n    function has_not_data_of_fired_events_if_data_tracking_is_disabled_in_config()\n    {\n        $this->app->make('config')->set('profiler.group.events', false);\n\n        $tracker = $this->app->make(EventsTracker::class);\n\n        $user = $this->user(['email' => 'a@example.com']);\n        $usersA = collect([$this->user(['email' => 'b@example.com']), $this->user(['email' => 'c@example.com'])]);\n        $usersB = [$this->user(['email' => 'd@example.com']), $this->user(['email' => 'e@example.com'])];\n        $dummyClasses = [new DummyClassA(), new DummyClassB()];\n        $dataA = ['a' => 1, 'c' => 2];\n        $dataB = 'c';\n\n        event(new DummyEventB($user, $usersA, $usersB, $dummyClasses, $dataA, $dataB));\n\n        $tracker->terminate();\n        $events = $tracker->data()->get('events');\n        $eventB = $events->where('name', DummyEventB::class)->first();\n\n        $this->assertArrayNotHasKey('data', $eventB);\n    }\n\n    /** @test */\n    function can_group_events_with_the_same_name()\n    {\n        $this->app->make('config')->set('profiler.data.events', true);\n\n        $tracker = $this->app->make(EventsTracker::class);\n        $dispatcher = $this->app->make(Dispatcher::class);\n\n        $this->tapLaravelVersionTill(5.3, function () use ($dispatcher) {\n            $dispatcher->fire('testing: eventA', [new \\stdClass()]);\n            $dispatcher->fire('testing: eventB', [new \\stdClass()]);\n            $dispatcher->fire('testing: eventB', [new \\stdClass()]);\n            $dispatcher->fire('testing: eventC', [new \\stdClass()]);\n            $dispatcher->fire('testing: eventC', [new \\stdClass()]);\n            $dispatcher->fire('testing: eventC', [new \\stdClass()]);\n            $dispatcher->fire('testing: eventC', [new \\stdClass()]);\n            $dispatcher->fire('testing: eventD', [new \\stdClass()]);\n        });\n        $this->tapLaravelVersionFrom(5.4, function () use ($dispatcher) {\n            $dispatcher->dispatch('testing: eventA', [new \\stdClass()]);\n            $dispatcher->dispatch('testing: eventB', [new \\stdClass()]);\n            $dispatcher->dispatch('testing: eventB', [new \\stdClass()]);\n            $dispatcher->dispatch('testing: eventC', [new \\stdClass()]);\n            $dispatcher->dispatch('testing: eventC', [new \\stdClass()]);\n            $dispatcher->dispatch('testing: eventC', [new \\stdClass()]);\n            $dispatcher->dispatch('testing: eventC', [new \\stdClass()]);\n            $dispatcher->dispatch('testing: eventD', [new \\stdClass()]);\n        });\n\n        $tracker->terminate();\n        $events = $tracker->data()->get('events');\n\n        $this->assertEquals([\n            'name' => 'testing: eventA',\n            'count' => 1,\n            'data' => collect([]),\n        ], $events->pull(0));\n        $this->assertEquals([\n            'name' => 'testing: eventB',\n            'count' => 2,\n        ], $events->pull(1));\n        $this->assertEquals([\n            'name' => 'testing: eventC',\n            'count' => 4,\n        ], $events->pull(2));\n        $this->assertEquals([\n            'name' => 'testing: eventD',\n            'count' => 1,\n            'data' => collect([]),\n        ], $events->pull(3));\n        $this->assertEquals(8, $tracker->meta()->get('events_count'));\n    }\n\n    /** @test */\n    function does_not_group_events_if_events_group_is_disabled_in_config()\n    {\n        $this->app->make('config')->set('profiler.data.events', true);\n        $this->app->make('config')->set('profiler.group.events', false);\n\n        $tracker = $this->app->make(EventsTracker::class);\n        $dispatcher = $this->app->make(Dispatcher::class);\n\n        $this->tapLaravelVersionTill(5.3, function () use ($dispatcher) {\n            $dispatcher->fire('testing: eventA', [new \\stdClass()]);\n            $dispatcher->fire('testing: eventB', [new \\stdClass()]);\n            $dispatcher->fire('testing: eventB', [new \\stdClass()]);\n        });\n        $this->tapLaravelVersionFrom(5.4, function () use ($dispatcher) {\n            $dispatcher->dispatch('testing: eventA', [new \\stdClass()]);\n            $dispatcher->dispatch('testing: eventB', [new \\stdClass()]);\n            $dispatcher->dispatch('testing: eventB', [new \\stdClass()]);\n        });\n\n        $tracker->terminate();\n        $events = $tracker->data()->get('events');\n\n        $this->assertEquals([\n            'name' => 'testing: eventA',\n            'count' => 1,\n            'data' => collect([]),\n        ], $events->pull(0));\n        $this->assertEquals([\n            'name' => 'testing: eventB',\n            'count' => 1,\n            'data' => collect([]),\n        ], $events->pull(1));\n        $this->assertEquals([\n            'name' => 'testing: eventB',\n            'count' => 1,\n            'data' => collect([]),\n        ], $events->pull(2));\n        $this->assertEquals(3, $tracker->meta()->get('events_count'));\n    }\n\n    /** @test */\n    function does_not_track_laravel_profiler_internal_events()\n    {\n        $tracker = $this->app->make(EventsTracker::class);\n\n        event(new ExceptionHandling(new Exception()));\n        event(new ProfilerBound());\n        event(new ResetTrackers());\n        event(new Terminating());\n        event(new Tracking());\n\n        $tracker->terminate();\n\n        $this->assertEquals(0, $tracker->meta()->get('events_count'));\n    }\n\n    /** @test */\n    function does_not_track_laravel_framework_events()\n    {\n        $tracker = $this->app->make(EventsTracker::class);\n\n        event('bootstrapped: ' . \\Illuminate\\Foundation\\Bootstrap\\BootProviders::class, [new \\stdClass()]);\n\n        $tracker->terminate();\n\n        $this->assertEquals(0, $tracker->meta()->get('events_count'));\n    }\n\n    /** @test */\n    function can_reset_events()\n    {\n        $tracker = $this->app->make(EventsTracker::class);\n        event(new DummyEventA());\n        event(new DummyEventA());\n        event(new DummyEventA());\n\n        profiler_reset();\n\n        event(new DummyEventA());\n\n        $tracker->terminate();\n\n        $this->assertEquals(1, $tracker->meta()->get('events_count'));\n        $this->assertCount(1, $tracker->data()->get('events'));\n    }\n}\n"
  },
  {
    "path": "tests/Unit/Trackers/ExceptionTrackerTest.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Unit\\Trackers;\n\nuse Mockery;\nuse Illuminate\\Support\\Arr;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Support\\Facades\\Route;\nuse JKocik\\Laravel\\Profiler\\Tests\\TestCase;\nuse JKocik\\Laravel\\Profiler\\Events\\ExceptionHandling;\nuse JKocik\\Laravel\\Profiler\\Trackers\\ExceptionTracker;\nuse Symfony\\Component\\HttpKernel\\Exception\\NotFoundHttpException;\nuse JKocik\\Laravel\\Profiler\\Tests\\Support\\Fixtures\\DummyException;\n\nclass ExceptionTrackerTest extends TestCase\n{\n    /**\n     * @var \\Exception\n     */\n    protected $exception;\n\n    /**\n     * @return void\n     */\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $this->turnOffProcessors();\n    }\n\n    /** @test */\n    function has_exception()\n    {\n        Event::listen(ExceptionHandling::class, function (ExceptionHandling $exceptionHandling) {\n            $this->exception = $exceptionHandling->exception;\n        });\n\n        $tracker = $this->app->make(ExceptionTracker::class);\n\n        $this->get('/i-can-not-find-that-page');\n\n        $tracker->terminate();\n        $exception = $tracker->data()->get('exception');\n\n        $this->assertSame($this->exception->getMessage(), $exception->get('message'));\n        $this->assertSame(NotFoundHttpException::class, $exception->get('exception'));\n        $this->assertSame($this->exception->getFile(), $exception->get('file'));\n        $this->assertSame($this->exception->getLine(), $exception->get('line'));\n        $this->assertEquals(collect($this->exception->getTrace())->map(function ($trace) {\n            return Arr::except($trace, ['args', 'type']);\n        }), $exception->get('trace'));\n    }\n\n    /** @test */\n    function has_not_exception_on_correct_framework_execution()\n    {\n        $tracker = $this->app->make(ExceptionTracker::class);\n\n        $this->get('/');\n\n        $tracker->terminate();\n        $exception = $tracker->data()->get('exception');\n\n        $this->assertNull($exception);\n    }\n\n    /** @test */\n    function calls_regular_laravel_exception_handler()\n    {\n        $this->tapLaravelVersionTill(5.4, function () {\n            $this->assertTrue(true);\n        });\n\n        $this->tapLaravelVersionFrom(5.5, function () {\n            $mock = Mockery::spy(DummyException::class);\n\n            Route::get('route-ex', function () use ($mock) {\n                throw $mock;\n            });\n\n            $tracker = $this->app->make(ExceptionTracker::class);\n\n            $this->get('/route-ex');\n\n            $mock->shouldHaveReceived('report')->once();\n        });\n    }\n}\n"
  },
  {
    "path": "tests/Unit/Trackers/PathsTrackerTest.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Unit\\Trackers;\n\nuse JKocik\\Laravel\\Profiler\\Tests\\TestCase;\nuse JKocik\\Laravel\\Profiler\\Trackers\\PathsTracker;\n\nclass PathsTrackerTest extends TestCase\n{\n    /** @test */\n    function has_app_path()\n    {\n        $tracker = $this->app->make(PathsTracker::class);\n\n        $tracker->terminate();\n        $paths = $tracker->data()->get('paths');\n\n        $this->assertEquals($this->app->path(), $paths->where('name', 'app_path')->first()['path']);\n        $this->assertSame(0, $paths->keys()[0]);\n    }\n\n    /** @test */\n    function has_base_path()\n    {\n        $tracker = $this->app->make(PathsTracker::class);\n\n        $tracker->terminate();\n        $paths = $tracker->data()->get('paths');\n\n        $this->assertEquals($this->app->basePath(), $paths->where('name', 'base_path')->first()['path']);\n    }\n\n    /** @test */\n    function has_lang_path()\n    {\n        $tracker = $this->app->make(PathsTracker::class);\n\n        $tracker->terminate();\n        $paths = $tracker->data()->get('paths');\n\n        $this->assertEquals($this->app->langPath(), $paths->where('name', 'lang_path')->first()['path']);\n    }\n\n    /** @test */\n    function has_config_path()\n    {\n        $tracker = $this->app->make(PathsTracker::class);\n\n        $tracker->terminate();\n        $paths = $tracker->data()->get('paths');\n\n        $this->assertEquals($this->app->configPath(), $paths->where('name', 'config_path')->first()['path']);\n    }\n\n    /** @test */\n    function has_public_path()\n    {\n        $tracker = $this->app->make(PathsTracker::class);\n\n        $tracker->terminate();\n        $paths = $tracker->data()->get('paths');\n\n        $this->assertEquals($this->app->publicPath(), $paths->where('name', 'public_path')->first()['path']);\n    }\n\n    /** @test */\n    function has_storage_path()\n    {\n        $tracker = $this->app->make(PathsTracker::class);\n\n        $tracker->terminate();\n        $paths = $tracker->data()->get('paths');\n\n        $this->assertEquals($this->app->storagePath(), $paths->where('name', 'storage_path')->first()['path']);\n    }\n\n    /** @test */\n    function has_database_path()\n    {\n        $tracker = $this->app->make(PathsTracker::class);\n\n        $tracker->terminate();\n        $paths = $tracker->data()->get('paths');\n\n        $this->assertEquals($this->app->databasePath(), $paths->where('name', 'database_path')->first()['path']);\n    }\n\n    /** @test */\n    function has_resource_path()\n    {\n        $tracker = $this->app->make(PathsTracker::class);\n\n        $tracker->terminate();\n        $paths = $tracker->data()->get('paths');\n\n        $this->tapLaravelVersionTill(5.2, function () use ($paths) {\n            $this->assertCount(0, $paths->where('name', 'resource_path'));\n        });\n\n        $this->tapLaravelVersionFrom(5.3, function () use ($paths) {\n            $this->assertEquals($this->app->resourcePath(), $paths->where('name', 'resource_path')->first()['path']);\n        });\n    }\n\n    /** @test */\n    function has_bootstrap_path()\n    {\n        $tracker = $this->app->make(PathsTracker::class);\n\n        $tracker->terminate();\n        $paths = $tracker->data()->get('paths');\n\n        $this->assertEquals($this->app->bootstrapPath(), $paths->where('name', 'bootstrap_path')->first()['path']);\n    }\n\n    /** @test */\n    function has_cached_config_path()\n    {\n        $tracker = $this->app->make(PathsTracker::class);\n\n        $tracker->terminate();\n        $paths = $tracker->data()->get('paths');\n\n        $this->assertEquals($this->app->getCachedConfigPath(), $paths->where('name', 'cached_config_path')->first()['path']);\n    }\n\n    /** @test */\n    function has_cached_routes_path()\n    {\n        $tracker = $this->app->make(PathsTracker::class);\n\n        $tracker->terminate();\n        $paths = $tracker->data()->get('paths');\n\n        $this->assertEquals($this->app->getCachedRoutesPath(), $paths->where('name', 'cached_routes_path')->first()['path']);\n    }\n\n    /** @test */\n    function has_cached_services_path()\n    {\n        $tracker = $this->app->make(PathsTracker::class);\n\n        $tracker->terminate();\n        $paths = $tracker->data()->get('paths');\n\n        $this->assertEquals($this->app->getCachedServicesPath(), $paths->where('name', 'cached_services_path')->first()['path']);\n    }\n\n    /** @test */\n    function has_cached_packages_path()\n    {\n        $tracker = $this->app->make(PathsTracker::class);\n\n        $tracker->terminate();\n        $paths = $tracker->data()->get('paths');\n\n        $this->tapLaravelVersionTill(5.4, function () use ($paths) {\n            $this->assertCount(0, $paths->where('name', 'cached_packages_path'));\n        });\n\n        $this->tapLaravelVersionFrom(5.5, function () use ($paths) {\n            $this->assertEquals($this->app->getCachedPackagesPath(), $paths->where('name', 'cached_packages_path')->first()['path']);\n        });\n    }\n\n    /** @test */\n    function has_environment_file_path()\n    {\n        $tracker = $this->app->make(PathsTracker::class);\n\n        $tracker->terminate();\n        $paths = $tracker->data()->get('paths');\n\n        $this->assertEquals($this->app->environmentFilePath(), $paths->where('name', 'environment_file_path')->first()['path']);\n    }\n}\n"
  },
  {
    "path": "tests/Unit/Trackers/QueriesTrackerTest.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Unit\\Trackers;\n\nuse Exception;\nuse Carbon\\Carbon;\nuse Illuminate\\Support\\Facades\\DB;\nuse Illuminate\\Support\\Facades\\Artisan;\nuse JKocik\\Laravel\\Profiler\\Tests\\TestCase;\nuse JKocik\\Laravel\\Profiler\\Trackers\\QueriesTracker;\n\nclass QueriesTrackerTest extends TestCase\n{\n    /**\n     * @return void\n     */\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        Artisan::call('migrate');\n    }\n\n    /**\n     * @return void\n     */\n    protected function tearDown(): void\n    {\n        parent::tearDown();\n\n        Artisan::call('migrate:rollback');\n    }\n\n    /** @test */\n    function has_executed_queries()\n    {\n        $tracker = $this->app->make(QueriesTracker::class);\n        $this->factoryUser()->create([\n            'name' => 'Joe',\n            'email' => 'joe@example.com',\n        ]);\n\n        $tracker->terminate();\n        $queries = $tracker->data()->get('queries');\n\n        $this->assertNotNull($queries);\n        $this->assertStringContainsString('query', $queries->first()['type']);\n        $this->assertStringContainsString('insert into `users` (`name`, `email`', $queries->first()['sql']);\n        $this->assertContains('joe@example.com', $queries->first()['bindings']);\n        $this->assertArrayHasKey('time', $queries->first());\n        $this->assertEquals(':memory:', $queries->first()['database']);\n        $this->assertEquals('sqlite', $queries->first()['name']);\n        $this->assertStringContainsString('insert into `users` (`name`, `email`', $queries->first()['query']);\n        $this->assertStringContainsString(\"values ('Joe', 'joe@example.com'\", $queries->first()['query']);\n    }\n\n    /** @test */\n    function has_committed_transactions()\n    {\n        $tracker = $this->app->make(QueriesTracker::class);\n        DB::transaction(function () {\n            $this->factoryUser()->create();\n        });\n\n        $tracker->terminate();\n        $queries = $tracker->data()->get('queries');\n\n        $this->assertStringContainsString('transaction-begin', $queries->first()['type']);\n        $this->assertEquals(':memory:', $queries->first()['database']);\n        $this->assertEquals('sqlite', $queries->first()['name']);\n\n        $this->assertStringContainsString('transaction-commit', $queries->last()['type']);\n        $this->assertEquals(':memory:', $queries->last()['database']);\n        $this->assertEquals('sqlite', $queries->last()['name']);\n    }\n\n    /** @test */\n    function has_rolled_back_transactions()\n    {\n        $tracker = $this->app->make(QueriesTracker::class);\n        try {\n            DB::transaction(function () {\n                throw new Exception();\n            });\n        } catch (Exception $e) {}\n\n        $tracker->terminate();\n        $queries = $tracker->data()->get('queries');\n\n        $this->assertStringContainsString('transaction-rollback', $queries->last()['type']);\n        $this->assertEquals(':memory:', $queries->last()['database']);\n        $this->assertEquals('sqlite', $queries->last()['name']);\n    }\n\n    /** @test */\n    function can_count_queries()\n    {\n        $tracker = $this->app->make(QueriesTracker::class);\n        DB::select('select * from users');\n        $this->factoryUser()->create();\n\n        $tracker->terminate();\n\n        $this->assertEquals(2, $tracker->meta()->get('queries_count'));\n    }\n\n    /** @test */\n    function can_count_queries_without_transactions()\n    {\n        $tracker = $this->app->make(QueriesTracker::class);\n        DB::transaction(function () {\n            DB::select('select * from users');\n            $this->factoryUser()->create();\n        });\n\n        $tracker->terminate();\n\n        $this->assertEquals(2, $tracker->meta()->get('queries_count'));\n    }\n\n    /** @test */\n    function has_bindings_keys_names_if_specified()\n    {\n        $tracker = $this->app->make(QueriesTracker::class);\n        DB::select('select * from users where email = :email and name = :name', ['email' => 'abc@example.com', 'name' => 1]);\n\n        $tracker->terminate();\n        $queries = $tracker->data()->get('queries');\n\n        $this->assertArrayHasKey('email', $queries->first()['bindings']);\n        $this->assertArrayHasKey('name', $queries->first()['bindings']);\n    }\n\n    /** @test */\n    function has_query_bindings_for_int_and_float_values()\n    {\n        $tracker = $this->app->make(QueriesTracker::class);\n        $this->userClass()::whereEmail(1)->first();\n        $this->userClass()::whereEmail(1.1)->first();\n        $this->userClass()::whereEmail('1')->first();\n        $this->userClass()::whereEmail('1.1')->first();\n\n        $tracker->terminate();\n        $queries = $tracker->data()->get('queries');\n\n        $this->assertStringContainsString(\"where `email` = 1\", $queries->shift()['query']);\n        $this->assertStringContainsString(\"where `email` = 1.1\", $queries->shift()['query']);\n        $this->assertStringContainsString(\"where `email` = '1'\", $queries->shift()['query']);\n        $this->assertStringContainsString(\"where `email` = '1.1'\", $queries->shift()['query']);\n    }\n\n    /** @test */\n    function has_query_bindings_for_null_values()\n    {\n        $tracker = $this->app->make(QueriesTracker::class);\n        $this->userClass()::whereNull('email')->first();\n        $this->userClass()::whereNotNull('email')->first();\n\n        $tracker->terminate();\n        $queries = $tracker->data()->get('queries');\n\n        $this->assertStringContainsString(\"where `email` is null\", $queries->shift()['query']);\n        $this->assertStringContainsString(\"where `email` is not null\", $queries->shift()['query']);\n    }\n\n    /** @test */\n    function has_query_bindings_for_bool_values()\n    {\n        $tracker = $this->app->make(QueriesTracker::class);\n        DB::select('select * from users where 1 = :first and 0 = :second', ['first' => true, 'second' => false]);\n\n        $tracker->terminate();\n        $queries = $tracker->data()->get('queries');\n\n        $this->tapLaravelVersionFrom(5.5, function () use ($queries) {\n            $this->assertStringContainsString(\"where 1 = 1 and 0 = 0\", $queries->first()['query']);\n            $this->assertSame(1, $queries->first()['bindings']['first']);\n            $this->assertSame(0, $queries->first()['bindings']['second']);\n        });\n\n        $this->tapLaravelVersionTill(5.4, function () use ($queries) {\n            $this->assertStringContainsString(\"where 1 = '1' and 0 = 0\", $queries->first()['query']);\n            $this->assertSame(true, $queries->first()['bindings']['first']);\n            $this->assertSame(0, $queries->first()['bindings']['second']);\n        });\n    }\n\n    /** @test */\n    function has_query_bindings_names_as_string()\n    {\n        $tracker = $this->app->make(QueriesTracker::class);\n        DB::select('select * from users where email = :email and name = :name', ['email' => 'abc@example.com', 'name' => 1]);\n\n        $tracker->terminate();\n        $queries = $tracker->data()->get('queries');\n\n        $this->assertStringContainsString(\"where email = 'abc@example.com' and name = 1\", $queries->first()['query']);\n    }\n\n    /** @test */\n    function has_query_bindings_objects()\n    {\n        $dateTime = Carbon::now();\n\n        $tracker = $this->app->make(QueriesTracker::class);\n        DB::select('select * from users where email = :email', ['email' => $dateTime]);\n\n        $tracker->terminate();\n        $queries = $tracker->data()->get('queries');\n\n        $this->assertStringContainsString(\"where email = '{$dateTime->toDateTimeString()}'\", $queries->first()['query']);\n    }\n\n    /** @test */\n    function has_query_bindings_truncated_if_binding_string_is_long()\n    {\n        $tracker = $this->app->make(QueriesTracker::class);\n        DB::select('select * from users where email = :email', ['email' => str_repeat('a', 255)]);\n        DB::select('select * from users where email = :email', ['email' => str_repeat('a', 256)]);\n\n        $tracker->terminate();\n        $queries = $tracker->data()->get('queries');\n\n        $this->assertStringContainsString(\"where email = '\". str_repeat('a', 255) .\"'\", $queries->first()['query']);\n        $this->assertContains(str_repeat('a', 255), $queries->first()['bindings']);\n        $this->assertStringContainsString(\"where email = '\". str_repeat('a', 255) .\"...{truncated}'\", $queries->last()['query']);\n        $this->assertContains(str_repeat('a', 255) . '...{truncated}', $queries->last()['bindings']);\n    }\n\n    /** @test */\n    function can_reset_queries()\n    {\n        $tracker = $this->app->make(QueriesTracker::class);\n        DB::select('select * from users');\n        DB::select('select * from users');\n        DB::select('select * from users');\n\n        profiler_reset();\n\n        DB::select('select * from users');\n\n        $tracker->terminate();\n\n        $this->assertEquals(1, $tracker->meta()->get('queries_count'));\n        $this->assertCount(1, $tracker->data()->get('queries'));\n    }\n}\n"
  },
  {
    "path": "tests/Unit/Trackers/RedisTrackerTest.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Unit\\Trackers;\n\nuse JKocik\\Laravel\\Profiler\\Tests\\TestCase;\nuse JKocik\\Laravel\\Profiler\\Trackers\\RedisTracker;\n\nclass RedisTrackerTest extends TestCase\n{\n    protected function setUp(): void\n    {\n        parent::setUp();\n    }\n\n    /** @test */\n    function has_executed_commands()\n    {\n        $tracker = $this->app->make(RedisTracker::class);\n        $this->app->make('redis')->set('name', 'Laravel Profiler');\n\n        $tracker->terminate();\n        $redis = $tracker->data()->get('redis');\n\n        $this->assertNotNull($redis);\n\n        $this->tapLaravelVersionTill(5.6, function () use ($redis) {\n            $this->assertEquals([], $redis->all());\n        });\n        $this->tapLaravelVersionFrom(5.7, function () use ($redis) {\n            $this->assertEquals('set', $redis->first()['command']);\n            $this->assertEquals('default', $redis->first()['name']);\n            $this->assertEquals(['name', 'Laravel Profiler'], $redis->first()['parameters']);\n            $this->assertArrayHasKey('time', $redis->first());\n        });\n    }\n\n    /** @test */\n    function can_count_commands()\n    {\n        $tracker = $this->app->make(RedisTracker::class);\n        $this->app->make('redis')->set('name', 'Laravel Profiler');\n        $this->app->make('redis')->set('action', 'testing');\n\n        $tracker->terminate();\n\n        $this->tapLaravelVersionTill(5.6, function () use ($tracker) {\n            $this->assertEquals(0, $tracker->meta()->get('redis_count'));\n        });\n        $this->tapLaravelVersionFrom(5.7, function () use ($tracker) {\n            $this->assertEquals(2, $tracker->meta()->get('redis_count'));\n        });\n    }\n\n    /** @test */\n    function knows_if_laravel_is_able_to_track_redis()\n    {\n        $tracker = $this->app->make(RedisTracker::class);\n\n        $tracker->terminate();\n\n        $this->tapLaravelVersionTill(5.6, function () use ($tracker) {\n            $this->assertFalse($tracker->meta()->get('redis_can_be_tracked'));\n        });\n        $this->tapLaravelVersionFrom(5.7, function () use ($tracker) {\n            $this->assertTrue($tracker->meta()->get('redis_can_be_tracked'));\n        });\n    }\n\n    /** @test */\n    function can_reset_commands()\n    {\n        $tracker = $this->app->make(RedisTracker::class);\n        $this->app->make('redis')->set('name', 'Laravel Profiler');\n        $this->app->make('redis')->set('name', 'Laravel Profiler');\n        $this->app->make('redis')->set('name', 'Laravel Profiler');\n\n        profiler_reset();\n\n        $this->app->make('redis')->set('name', 'Laravel Profiler');\n\n        $tracker->terminate();\n\n        $this->tapLaravelVersionTill(5.6, function () {\n            $this->assertTrue(true);\n        });\n        $this->tapLaravelVersionFrom(5.7, function () use ($tracker) {\n            $this->assertEquals(1, $tracker->meta()->get('redis_count'));\n            $this->assertCount(1, $tracker->data()->get('redis'));\n        });\n    }\n}\n"
  },
  {
    "path": "tests/Unit/Trackers/RequestTrackerTest.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Unit\\Trackers;\n\nuse Mockery;\nuse JKocik\\Laravel\\Profiler\\Tests\\TestCase;\nuse JKocik\\Laravel\\Profiler\\Trackers\\RequestTracker;\nuse JKocik\\Laravel\\Profiler\\Contracts\\ExecutionData;\nuse JKocik\\Laravel\\Profiler\\Contracts\\ExecutionRequest;\n\nclass RequestTrackerTest extends TestCase\n{\n    /** @test */\n    function has_request_meta()\n    {\n        $request = Mockery::mock(ExecutionRequest::class)->shouldIgnoreMissing();\n        $request->shouldReceive('meta')->once()->andReturn(collect([\n            'key-a' => 'val-a',\n            'key-b' => 'val-b',\n            'key-c' => 'val-c',\n        ]));\n        $this->app->make(ExecutionData::class)->setRequest($request);\n\n        $tracker = $this->app->make(RequestTracker::class);\n        $tracker->terminate();\n\n        $this->assertEquals('val-a', $tracker->meta()->get('key-a'));\n        $this->assertEquals('val-b', $tracker->meta()->get('key-b'));\n        $this->assertEquals('val-c', $tracker->meta()->get('key-c'));\n    }\n\n    /** @test */\n    function has_request_data()\n    {\n        $request = Mockery::mock(ExecutionRequest::class)->shouldIgnoreMissing();\n        $request->shouldReceive('data')->once()->andReturn(collect([\n            ['name' => 'key-x', 'value' => 'val-x'],\n            ['name' => 'key-y', 'value' => 'val-y'],\n            ['name' => 'key-z', 'value' => 'val-z'],\n        ]));\n        $this->app->make(ExecutionData::class)->setRequest($request);\n\n        $tracker = $this->app->make(RequestTracker::class);\n        $tracker->terminate();\n\n        $this->assertEquals('val-x', $tracker->data()->get('request')->where('name', 'key-x')->first()['value']);\n        $this->assertEquals('val-y', $tracker->data()->get('request')->where('name', 'key-y')->first()['value']);\n        $this->assertEquals('val-z', $tracker->data()->get('request')->where('name', 'key-z')->first()['value']);\n    }\n}\n"
  },
  {
    "path": "tests/Unit/Trackers/ResponseTrackerTest.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Unit\\Trackers;\n\nuse Mockery;\nuse JKocik\\Laravel\\Profiler\\Tests\\TestCase;\nuse JKocik\\Laravel\\Profiler\\Contracts\\ExecutionData;\nuse JKocik\\Laravel\\Profiler\\Trackers\\ResponseTracker;\nuse JKocik\\Laravel\\Profiler\\Contracts\\ExecutionResponse;\n\nclass ResponseTrackerTest extends TestCase\n{\n    /** @test */\n    function has_response_meta()\n    {\n        $response = Mockery::mock(ExecutionResponse::class)->shouldIgnoreMissing();\n        $response->shouldReceive('meta')->once()->andReturn(collect([\n            'key-a' => 'val-a',\n            'key-b' => 'val-b',\n            'key-c' => 'val-c',\n        ]));\n        $this->app->make(ExecutionData::class)->setResponse($response);\n\n        $tracker = $this->app->make(ResponseTracker::class);\n        $tracker->terminate();\n\n        $this->assertEquals('val-a', $tracker->meta()->get('key-a'));\n        $this->assertEquals('val-b', $tracker->meta()->get('key-b'));\n        $this->assertEquals('val-c', $tracker->meta()->get('key-c'));\n    }\n\n    /** @test */\n    function has_response_data()\n    {\n        $response = Mockery::mock(ExecutionResponse::class)->shouldIgnoreMissing();\n        $response->shouldReceive('data')->once()->andReturn(collect([\n            ['name' => 'key-x', 'value' => 'val-x'],\n            ['name' => 'key-y', 'value' => 'val-y'],\n            ['name' => 'key-z', 'value' => 'val-z'],\n        ]));\n        $this->app->make(ExecutionData::class)->setResponse($response);\n\n        $tracker = $this->app->make(ResponseTracker::class);\n        $tracker->terminate();\n\n        $this->assertEquals('val-x', $tracker->data()->get('response')->where('name', 'key-x')->first()['value']);\n        $this->assertEquals('val-y', $tracker->data()->get('response')->where('name', 'key-y')->first()['value']);\n        $this->assertEquals('val-z', $tracker->data()->get('response')->where('name', 'key-z')->first()['value']);\n    }\n}\n"
  },
  {
    "path": "tests/Unit/Trackers/RouteTrackerTest.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Unit\\Trackers;\n\nuse Mockery;\nuse JKocik\\Laravel\\Profiler\\Tests\\TestCase;\nuse JKocik\\Laravel\\Profiler\\Trackers\\RouteTracker;\nuse JKocik\\Laravel\\Profiler\\Contracts\\ExecutionData;\nuse JKocik\\Laravel\\Profiler\\Contracts\\ExecutionRoute;\n\nclass RouteTrackerTest extends TestCase\n{\n    /** @test */\n    function has_route_meta()\n    {\n        $route = Mockery::mock(ExecutionRoute::class)->shouldIgnoreMissing();\n        $route->shouldReceive('meta')->once()->andReturn(collect([\n            'key-a' => 'val-a',\n            'key-b' => 'val-b',\n            'key-c' => 'val-c',\n        ]));\n        $this->app->make(ExecutionData::class)->setRoute($route);\n\n        $tracker = $this->app->make(RouteTracker::class);\n        $tracker->terminate();\n\n        $this->assertEquals('val-a', $tracker->meta()->get('key-a'));\n        $this->assertEquals('val-b', $tracker->meta()->get('key-b'));\n        $this->assertEquals('val-c', $tracker->meta()->get('key-c'));\n    }\n\n    /** @test */\n    function has_route_data()\n    {\n        $route = Mockery::mock(ExecutionRoute::class)->shouldIgnoreMissing();\n        $route->shouldReceive('data')->once()->andReturn(collect([\n            ['name' => 'key-x', 'value' => 'val-x'],\n            ['name' => 'key-y', 'value' => 'val-y'],\n            ['name' => 'key-z', 'value' => 'val-z'],\n        ]));\n        $this->app->make(ExecutionData::class)->setRoute($route);\n\n        $tracker = $this->app->make(RouteTracker::class);\n        $tracker->terminate();\n\n        $this->assertEquals('val-x', $tracker->data()->get('route')->where('name', 'key-x')->first()['value']);\n        $this->assertEquals('val-y', $tracker->data()->get('route')->where('name', 'key-y')->first()['value']);\n        $this->assertEquals('val-z', $tracker->data()->get('route')->where('name', 'key-z')->first()['value']);\n    }\n}\n"
  },
  {
    "path": "tests/Unit/Trackers/ServerTrackerTest.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Unit\\Trackers;\n\nuse Mockery;\nuse JKocik\\Laravel\\Profiler\\Tests\\TestCase;\nuse JKocik\\Laravel\\Profiler\\Trackers\\ServerTracker;\nuse JKocik\\Laravel\\Profiler\\Contracts\\ExecutionData;\nuse JKocik\\Laravel\\Profiler\\Contracts\\ExecutionServer;\n\nclass ServerTrackerTest extends TestCase\n{\n    /** @test */\n    function has_server_meta()\n    {\n        $server = Mockery::mock(ExecutionServer::class)->shouldIgnoreMissing();\n        $server->shouldReceive('meta')->once()->andReturn(collect([\n            'key-a' => 'val-a',\n            'key-b' => 'val-b',\n            'key-c' => 'val-c',\n        ]));\n        $this->app->make(ExecutionData::class)->setServer($server);\n\n        $tracker = $this->app->make(ServerTracker::class);\n        $tracker->terminate();\n\n        $this->assertEquals('val-a', $tracker->meta()->get('key-a'));\n        $this->assertEquals('val-b', $tracker->meta()->get('key-b'));\n        $this->assertEquals('val-c', $tracker->meta()->get('key-c'));\n    }\n\n    /** @test */\n    function has_server_data()\n    {\n        $server = Mockery::mock(ExecutionServer::class)->shouldIgnoreMissing();\n        $server->shouldReceive('data')->once()->andReturn(collect([\n            ['name' => 'key-x', 'value' => 'val-x'],\n            ['name' => 'key-y', 'value' => 'val-y'],\n            ['name' => 'key-z', 'value' => 'val-z'],\n        ]));\n        $this->app->make(ExecutionData::class)->setServer($server);\n\n        $tracker = $this->app->make(ServerTracker::class);\n        $tracker->terminate();\n\n        $this->assertEquals('val-x', $tracker->data()->get('server')->where('name', 'key-x')->first()['value']);\n        $this->assertEquals('val-y', $tracker->data()->get('server')->where('name', 'key-y')->first()['value']);\n        $this->assertEquals('val-z', $tracker->data()->get('server')->where('name', 'key-z')->first()['value']);\n    }\n}\n"
  },
  {
    "path": "tests/Unit/Trackers/ServiceProvidersTrackerTest.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Unit\\Trackers;\n\nuse Illuminate\\Support\\ServiceProvider;\nuse JKocik\\Laravel\\Profiler\\Tests\\TestCase;\nuse JKocik\\Laravel\\Profiler\\Trackers\\ServiceProvidersTracker;\n\nclass ServiceProvidersTrackerTest extends TestCase\n{\n    /** @test */\n    function has_loaded_service_providers()\n    {\n        $provider = new class($this->app) extends ServiceProvider {\n            public function register() {}\n        };\n        $this->app->register($provider);\n        $tracker = $this->app->make(ServiceProvidersTracker::class);\n\n        $tracker->terminate();\n        $serviceProviders = $tracker->data()->get('service_providers');\n\n        $this->assertNotNull($serviceProviders);\n        $this->assertTrue($serviceProviders->contains(get_class($provider)));\n        $this->assertCount(count($serviceProviders), $this->app->getLoadedProviders());\n        $this->assertSame(0, $serviceProviders->keys()[0]);\n    }\n}\n"
  },
  {
    "path": "tests/Unit/Trackers/SessionTrackerTest.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Unit\\Trackers;\n\nuse Mockery;\nuse JKocik\\Laravel\\Profiler\\Tests\\TestCase;\nuse JKocik\\Laravel\\Profiler\\Trackers\\SessionTracker;\nuse JKocik\\Laravel\\Profiler\\Contracts\\ExecutionData;\nuse JKocik\\Laravel\\Profiler\\Contracts\\ExecutionSession;\n\nclass SessionTrackerTest extends TestCase\n{\n    /** @test */\n    function has_session_meta()\n    {\n        $session = Mockery::mock(ExecutionSession::class)->shouldIgnoreMissing();\n        $session->shouldReceive('meta')->once()->andReturn(collect([\n            'key-a' => 'val-a',\n            'key-b' => 'val-b',\n            'key-c' => 'val-c',\n        ]));\n        $this->app->make(ExecutionData::class)->setSession($session);\n\n        $tracker = $this->app->make(SessionTracker::class);\n        $tracker->terminate();\n\n        $this->assertEquals('val-a', $tracker->meta()->get('key-a'));\n        $this->assertEquals('val-b', $tracker->meta()->get('key-b'));\n        $this->assertEquals('val-c', $tracker->meta()->get('key-c'));\n    }\n\n    /** @test */\n    function has_session_data()\n    {\n        $session = Mockery::mock(ExecutionSession::class)->shouldIgnoreMissing();\n        $session->shouldReceive('data')->once()->andReturn(collect([\n            ['name' => 'key-x', 'value' => 'val-x'],\n            ['name' => 'key-y', 'value' => 'val-y'],\n            ['name' => 'key-z', 'value' => 'val-z'],\n        ]));\n        $this->app->make(ExecutionData::class)->setSession($session);\n\n        $tracker = $this->app->make(SessionTracker::class);\n        $tracker->terminate();\n\n        $this->assertEquals('val-x', $tracker->data()->get('session')->where('name', 'key-x')->first()['value']);\n        $this->assertEquals('val-y', $tracker->data()->get('session')->where('name', 'key-y')->first()['value']);\n        $this->assertEquals('val-z', $tracker->data()->get('session')->where('name', 'key-z')->first()['value']);\n    }\n}\n"
  },
  {
    "path": "tests/Unit/Trackers/ViewsTrackerTest.php",
    "content": "<?php\n\nnamespace JKocik\\Laravel\\Profiler\\Tests\\Unit\\Trackers;\n\nuse JKocik\\Laravel\\Profiler\\Tests\\TestCase;\nuse JKocik\\Laravel\\Profiler\\Trackers\\ViewsTracker;\n\nclass ViewsTrackerTest extends TestCase\n{\n    /**\n     * @return void\n     */\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $this->app['view']->addNamespace('tests', __DIR__ . '/../../Support/Fixtures');\n    }\n\n    /** @test */\n    function has_views()\n    {\n        $tracker = $this->app->make(ViewsTracker::class);\n\n        view('tests::dummy-view-a')->render();\n        view('tests::dummy-view-b')->render();\n\n        $tracker->terminate();\n        $views = $tracker->data()->get('views');\n\n        $this->assertNotNull($views);\n        $this->assertCount(2, $views);\n    }\n\n    /** @test */\n    function has_view_name()\n    {\n        $tracker = $this->app->make(ViewsTracker::class);\n\n        view('tests::dummy-view-a')->render();\n\n        $tracker->terminate();\n        $views = $tracker->data()->get('views');\n\n        $this->assertEquals('tests::dummy-view-a', $views->first()['name']);\n    }\n\n    /** @test */\n    function has_view_path()\n    {\n        $tracker = $this->app->make(ViewsTracker::class);\n\n        view('tests::dummy-view-a')->render();\n\n        $tracker->terminate();\n        $views = $tracker->data()->get('views');\n\n        $this->assertEquals(__DIR__ . '/../../Support/Fixtures/dummy-view-a.blade.php', $views->first()['path']);\n    }\n\n    /** @test */\n    function has_view_data()\n    {\n        $this->app->make('config')->set('profiler.data.views', true);\n\n        $tracker = $this->app->make(ViewsTracker::class);\n\n        $user = ['name' => 'Joe'];\n        view('tests::dummy-view-a', compact('user'))->render();\n\n        $tracker->terminate();\n        $views = $tracker->data()->get('views');\n\n        $this->assertEquals(['name' => 'Joe'], $views->first()['data']['user']);\n        $this->assertArrayNotHasKey('params', $views->first());\n    }\n\n    /** @test */\n    function has_not_data_of_views_if_data_tracking_is_disabled_in_config()\n    {\n        $tracker = $this->app->make(ViewsTracker::class);\n\n        $user = ['name' => 'Joe'];\n        view('tests::dummy-view-a', compact('user'))->render();\n\n        $tracker->terminate();\n        $views = $tracker->data()->get('views');\n\n        $this->assertArrayNotHasKey('data', $views->first());\n    }\n\n    /** @test */\n    function has_view_params_if_data_tracking_is_disabled_in_config()\n    {\n        $tracker = $this->app->make(ViewsTracker::class);\n\n        $name = 'Joe';\n        $visits = 125;\n        $price = 5.89;\n        $active = true;\n        $address = null;\n        $related = $this->user(['email' => 'a@example.com']);\n        $roles = collect(['publisher', 'viewer']);\n        $tags = ['a'];\n        $comments = [];\n        view('tests::dummy-view-a', compact(\n            'name',\n            'visits',\n            'price',\n            'active',\n            'address',\n            'related',\n            'roles',\n            'tags',\n            'comments'\n        ))->render();\n\n        $tracker->terminate();\n        $views = $tracker->data()->get('views');\n\n        $this->assertArrayNotHasKey('data', $views->first());\n        $this->assertEquals([\n            'name' => 'string',\n            'visits' => 'integer',\n            'price' => 'double',\n            'active' => 'boolean',\n            'address' => 'NULL',\n            'related' => $this->userClass(),\n            'roles' => 'Illuminate\\Support\\Collection: 2 item(s)',\n            'tags' => 'array: 1 item(s)',\n            'comments' => 'array: 0 item(s)',\n        ], $views->first()['params']);\n    }\n\n    /** @test */\n    function can_reset_views()\n    {\n        $tracker = $this->app->make(ViewsTracker::class);\n        view('tests::dummy-view-a')->render();\n        view('tests::dummy-view-a')->render();\n        view('tests::dummy-view-a')->render();\n\n        profiler_reset();\n\n        view('tests::dummy-view-a')->render();\n\n        $tracker->terminate();\n\n        $this->assertCount(1, $tracker->data()->get('views'));\n    }\n}\n"
  },
  {
    "path": "tests/bootstrap/phpunit.php",
    "content": "<?php\n\nrequire_once __DIR__ . '/../../vendor/autoload.php';\n\n$framework = new \\JKocik\\Laravel\\Profiler\\Tests\\Support\\Framework();\n\nrequire_once bootstrapFramework($framework);\n\nbootstrapFrameworkEnv($framework);\n\n/**\n * @param \\JKocik\\Laravel\\Profiler\\Tests\\Support\\Framework $framework\n * @return string\n */\nfunction bootstrapFramework(\\JKocik\\Laravel\\Profiler\\Tests\\Support\\Framework $framework): string\n{\n    $frameworkAutoloadFile = __DIR__ . '/../../frameworks/' . $framework->dir() . '/vendor/autoload.php';\n\n    if (! file_exists($frameworkAutoloadFile)) {\n        shell_exec('composer create-project --no-dev ' . $framework->composerPackage() . ' ./frameworks/' . $framework->dir());\n    }\n\n    return $frameworkAutoloadFile;\n}\n\n/**\n * @param \\JKocik\\Laravel\\Profiler\\Tests\\Support\\Framework $framework\n * @return void\n */\nfunction bootstrapFrameworkEnv(\\JKocik\\Laravel\\Profiler\\Tests\\Support\\Framework $framework): void\n{\n    $frameworkPath = __DIR__ . '/../../frameworks/' . $framework->dir();\n\n    if (! file_exists($frameworkPath . '/.env')) {\n        copy($frameworkPath . '/.env.example', $frameworkPath . '/.env');\n    }\n}\n"
  }
]