diff --git a/app/Providers/QueryListenProvider.php b/app/Providers/QueryListenProvider.php
new file mode 100644
index 000000000..7ffdead0f
--- /dev/null
+++ b/app/Providers/QueryListenProvider.php
@@ -0,0 +1,25 @@
+sql, [$query->time]);
+ });
+
+ $this->app['router']->aliasMiddleware('clockwork', ClockworkMiddleware::class);
+ }
+}
diff --git a/composer.json b/composer.json
index 76a932a9d..c8029d6bb 100644
--- a/composer.json
+++ b/composer.json
@@ -35,6 +35,10 @@
{
"type": "vcs",
"url": "https://github.com/sandesh556/pdf-laravel5.git"
+ },
+ {
+ "type": "vcs",
+ "url": "https://github.com/ladybirdweb/clockwork.git"
}
],
"require": {
@@ -70,7 +74,8 @@
"unisharp/laravel-ckeditor": "dev-master",
"thomaswelton/laravel-gravatar": "dev-master",
"symfony/mailgun-mailer": "^6.2",
- "symfony/http-client": "^6.2"
+ "symfony/http-client": "^6.2",
+ "itsgoingd/clockwork": "dev-master"
},
"require-dev": {
"phpunit/phpunit": "^9.5.10",
@@ -81,9 +86,10 @@
"nunomaduro/collision": "^6.3",
"mockery/mockery": "^1.4.4",
"fakerphp/faker": "^1.9.1",
- "barryvdh/laravel-debugbar": "^3.7",
+ "barryvdh/laravel-debugbar": "^3.8",
"spatie/laravel-ignition": "^1.4",
- "laravel/pint": "^1.4"
+ "laravel/pint": "^1.4",
+ "beyondcode/laravel-query-detector": "^1.7"
},
"autoload": {
"classmap": [
diff --git a/composer.lock b/composer.lock
index 198b4400b..d8cf50e2a 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "de4b83b369c705c49ee38aa8f3984384",
+ "content-hash": "ec936e44c27edb7acd9fdd54c2266a10",
"packages": [
{
"name": "aws/aws-crt-php",
@@ -2558,6 +2558,73 @@
],
"time": "2022-05-21T17:30:32+00:00"
},
+ {
+ "name": "itsgoingd/clockwork",
+ "version": "dev-master",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/ladybirdweb/clockwork.git",
+ "reference": "e29be8125ce999947d60986dcd8e606c04c012ab"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/ladybirdweb/clockwork/zipball/e29be8125ce999947d60986dcd8e606c04c012ab",
+ "reference": "e29be8125ce999947d60986dcd8e606c04c012ab",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "php": ">=5.6"
+ },
+ "default-branch": true,
+ "type": "library",
+ "extra": {
+ "laravel": {
+ "providers": [
+ "Clockwork\\Support\\Laravel\\ClockworkServiceProvider"
+ ],
+ "aliases": {
+ "Clockwork": "Clockwork\\Support\\Laravel\\Facade"
+ }
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Clockwork\\": "Clockwork/"
+ }
+ },
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "itsgoingd",
+ "email": "itsgoingd@luzer.sk",
+ "homepage": "https://twitter.com/itsgoingd"
+ }
+ ],
+ "description": "php dev tools in your browser",
+ "homepage": "https://underground.works/clockwork",
+ "keywords": [
+ "debugging",
+ "devtools",
+ "laravel",
+ "logging",
+ "lumen",
+ "profiling",
+ "slim"
+ ],
+ "support": {
+ "source": "https://github.com/ladybirdweb/clockwork/tree/master"
+ },
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/itsgoingd"
+ }
+ ],
+ "time": "2023-04-14T10:39:18+00:00"
+ },
{
"name": "laravel/framework",
"version": "v9.52.0",
@@ -10063,30 +10130,30 @@
"packages-dev": [
{
"name": "barryvdh/laravel-debugbar",
- "version": "v3.7.0",
+ "version": "v3.8.0",
"source": {
"type": "git",
"url": "https://github.com/barryvdh/laravel-debugbar.git",
- "reference": "3372ed65e6d2039d663ed19aa699956f9d346271"
+ "reference": "eb01216141e62433178c52b0cbdb785b45bae871"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/3372ed65e6d2039d663ed19aa699956f9d346271",
- "reference": "3372ed65e6d2039d663ed19aa699956f9d346271",
+ "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/eb01216141e62433178c52b0cbdb785b45bae871",
+ "reference": "eb01216141e62433178c52b0cbdb785b45bae871",
"shasum": ""
},
"require": {
- "illuminate/routing": "^7|^8|^9",
- "illuminate/session": "^7|^8|^9",
- "illuminate/support": "^7|^8|^9",
+ "illuminate/routing": "^9|^10",
+ "illuminate/session": "^9|^10",
+ "illuminate/support": "^9|^10",
"maximebf/debugbar": "^1.17.2",
- "php": ">=7.2.5",
- "symfony/finder": "^5|^6"
+ "php": "^8.0",
+ "symfony/finder": "^6"
},
"require-dev": {
"mockery/mockery": "^1.3.3",
- "orchestra/testbench-dusk": "^5|^6|^7",
- "phpunit/phpunit": "^8.5|^9.0",
+ "orchestra/testbench-dusk": "^5|^6|^7|^8",
+ "phpunit/phpunit": "^8.5.30|^9.0",
"squizlabs/php_codesniffer": "^3.5"
},
"type": "library",
@@ -10131,7 +10198,7 @@
],
"support": {
"issues": "https://github.com/barryvdh/laravel-debugbar/issues",
- "source": "https://github.com/barryvdh/laravel-debugbar/tree/v3.7.0"
+ "source": "https://github.com/barryvdh/laravel-debugbar/tree/v3.8.0"
},
"funding": [
{
@@ -10143,7 +10210,67 @@
"type": "github"
}
],
- "time": "2022-07-11T09:26:42+00:00"
+ "time": "2023-02-04T15:47:28+00:00"
+ },
+ {
+ "name": "beyondcode/laravel-query-detector",
+ "version": "1.7.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/beyondcode/laravel-query-detector.git",
+ "reference": "40c7e168fcf7eeb80d8e96f7922e05ab194269c8"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/beyondcode/laravel-query-detector/zipball/40c7e168fcf7eeb80d8e96f7922e05ab194269c8",
+ "reference": "40c7e168fcf7eeb80d8e96f7922e05ab194269c8",
+ "shasum": ""
+ },
+ "require": {
+ "illuminate/support": "^5.5 || ^6.0 || ^7.0 || ^8.0 || ^9.0|^10.0",
+ "php": "^7.1 || ^8.0"
+ },
+ "require-dev": {
+ "laravel/legacy-factories": "^1.0",
+ "orchestra/testbench": "^3.0 || ^4.0 || ^5.0 || ^6.0|^8.0",
+ "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0"
+ },
+ "type": "library",
+ "extra": {
+ "laravel": {
+ "providers": [
+ "BeyondCode\\QueryDetector\\QueryDetectorServiceProvider"
+ ]
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "BeyondCode\\QueryDetector\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Marcel Pociot",
+ "email": "marcel@beyondco.de",
+ "homepage": "https://beyondcode.de",
+ "role": "Developer"
+ }
+ ],
+ "description": "Laravel N+1 Query Detector",
+ "homepage": "https://github.com/beyondcode/laravel-query-detector",
+ "keywords": [
+ "beyondcode",
+ "laravel-query-detector"
+ ],
+ "support": {
+ "issues": "https://github.com/beyondcode/laravel-query-detector/issues",
+ "source": "https://github.com/beyondcode/laravel-query-detector/tree/1.7.0"
+ },
+ "time": "2023-02-15T10:37:22+00:00"
},
{
"name": "doctrine/instantiator",
@@ -13321,7 +13448,8 @@
"chumper/zipper": 20,
"brozot/laravel-fcm": 20,
"unisharp/laravel-ckeditor": 20,
- "thomaswelton/laravel-gravatar": 20
+ "thomaswelton/laravel-gravatar": 20,
+ "itsgoingd/clockwork": 20
},
"prefer-stable": false,
"prefer-lowest": false,
diff --git a/config/app.php b/config/app.php
index 1dea56ca6..0319c9597 100644
--- a/config/app.php
+++ b/config/app.php
@@ -186,6 +186,8 @@ return [
\Yajra\DataTables\DataTablesServiceProvider::class,
\Bugsnag\BugsnagLaravel\BugsnagServiceProvider::class,
Maatwebsite\Excel\ExcelServiceProvider::class,
+ App\Providers\QueryListenProvider::class
+
],
/*
|--------------------------------------------------------------------------
diff --git a/config/clockwork.php b/config/clockwork.php
new file mode 100644
index 000000000..92333215c
--- /dev/null
+++ b/config/clockwork.php
@@ -0,0 +1,417 @@
+ env('CLOCKWORK_ENABLE', null),
+ 'middlewares'=>['web','auth','roles'],
+
+ /*
+ |------------------------------------------------------------------------------------------------------------------
+ | Features
+ |------------------------------------------------------------------------------------------------------------------
+ |
+ | You can enable or disable various Clockwork features here. Some features have additional settings (eg. slow query
+ | threshold for database queries).
+ |
+ */
+
+ 'features' => [
+
+ // Cache usage stats and cache queries including results
+ 'cache' => [
+ 'enabled' => env('CLOCKWORK_CACHE_ENABLED', true),
+
+ // Collect cache queries
+ 'collect_queries' => env('CLOCKWORK_CACHE_QUERIES', true),
+
+ // Collect values from cache queries (high performance impact with a very high number of queries)
+ 'collect_values' => env('CLOCKWORK_CACHE_COLLECT_VALUES', false)
+ ],
+
+ // Database usage stats and queries
+ 'database' => [
+ 'enabled' => env('CLOCKWORK_DATABASE_ENABLED', true),
+
+ // Collect database queries (high performance impact with a very high number of queries)
+ 'collect_queries' => env('CLOCKWORK_DATABASE_COLLECT_QUERIES', true),
+
+ // Collect details of models updates (high performance impact with a lot of model updates)
+ 'collect_models_actions' => env('CLOCKWORK_DATABASE_COLLECT_MODELS_ACTIONS', true),
+
+ // Collect details of retrieved models (very high performance impact with a lot of models retrieved)
+ 'collect_models_retrieved' => env('CLOCKWORK_DATABASE_COLLECT_MODELS_RETRIEVED', false),
+
+ // Query execution time threshold in milliseconds after which the query will be marked as slow
+ 'slow_threshold' => env('CLOCKWORK_DATABASE_SLOW_THRESHOLD'),
+
+ // Collect only slow database queries
+ 'slow_only' => env('CLOCKWORK_DATABASE_SLOW_ONLY', false),
+
+ // Detect and report duplicate queries
+ 'detect_duplicate_queries' => env('CLOCKWORK_DATABASE_DETECT_DUPLICATE_QUERIES', false)
+ ],
+
+ // Dispatched events
+ 'events' => [
+ 'enabled' => env('CLOCKWORK_EVENTS_ENABLED', true),
+
+ // Ignored events (framework events are ignored by default)
+ 'ignored_events' => [
+ // App\Events\UserRegistered::class,
+ // 'user.registered'
+ ],
+ ],
+
+ // Laravel log (you can still log directly to Clockwork with laravel log disabled)
+ 'log' => [
+ 'enabled' => env('CLOCKWORK_LOG_ENABLED', true)
+ ],
+
+ // Sent notifications
+ 'notifications' => [
+ 'enabled' => env('CLOCKWORK_NOTIFICATIONS_ENABLED', true),
+ ],
+
+ // Performance metrics
+ 'performance' => [
+ // Allow collecting of client metrics. Requires separate clockwork-browser npm package.
+ 'client_metrics' => env('CLOCKWORK_PERFORMANCE_CLIENT_METRICS', true)
+ ],
+
+ // Dispatched queue jobs
+ 'queue' => [
+ 'enabled' => env('CLOCKWORK_QUEUE_ENABLED', true)
+ ],
+
+ // Redis commands
+ 'redis' => [
+ 'enabled' => env('CLOCKWORK_REDIS_ENABLED', true)
+ ],
+
+ // Routes list
+ 'routes' => [
+ 'enabled' => env('CLOCKWORK_ROUTES_ENABLED', false),
+
+ // Collect only routes from particular namespaces (only application routes by default)
+ 'only_namespaces' => [ 'App' ]
+ ],
+
+ // Rendered views
+ 'views' => [
+ 'enabled' => env('CLOCKWORK_VIEWS_ENABLED', true),
+
+ // Collect views including view data (high performance impact with a high number of views)
+ 'collect_data' => env('CLOCKWORK_VIEWS_COLLECT_DATA', false),
+
+ // Use Twig profiler instead of Laravel events for apps using laravel-twigbridge (more precise, but does
+ // not support collecting view data)
+ 'use_twig_profiler' => env('CLOCKWORK_VIEWS_USE_TWIG_PROFILER', false)
+ ]
+
+ ],
+
+ /*
+ |------------------------------------------------------------------------------------------------------------------
+ | Enable web UI
+ |------------------------------------------------------------------------------------------------------------------
+ |
+ | Clockwork comes with a web UI accessible via http://your.app/clockwork. Here you can enable or disable this
+ | feature. You can also set a custom path for the web UI.
+ |
+ */
+
+ 'web' => env('CLOCKWORK_WEB', true),
+
+ /*
+ |------------------------------------------------------------------------------------------------------------------
+ | Enable toolbar
+ |------------------------------------------------------------------------------------------------------------------
+ |
+ | Clockwork can show a toolbar with basic metrics on all responses. Here you can enable or disable this feature.
+ | Requires a separate clockwork-browser npm library.
+ | For installation instructions see https://underground.works/clockwork/#docs-viewing-data
+ |
+ */
+
+ 'toolbar' => env('CLOCKWORK_TOOLBAR', true),
+
+ /*
+ |------------------------------------------------------------------------------------------------------------------
+ | HTTP requests collection
+ |------------------------------------------------------------------------------------------------------------------
+ |
+ | Clockwork collects data about HTTP requests to your app. Here you can choose which requests should be collected.
+ |
+ */
+
+ 'requests' => [
+ // With on-demand mode enabled, Clockwork will only profile requests when the browser extension is open or you
+ // manually pass a "clockwork-profile" cookie or get/post data key.
+ // Optionally you can specify a "secret" that has to be passed as the value to enable profiling.
+ 'on_demand' => env('CLOCKWORK_REQUESTS_ON_DEMAND', false),
+
+ // Collect only errors (requests with HTTP 4xx and 5xx responses)
+ 'errors_only' => env('CLOCKWORK_REQUESTS_ERRORS_ONLY', false),
+
+ // Response time threshold in milliseconds after which the request will be marked as slow
+ 'slow_threshold' => env('CLOCKWORK_REQUESTS_SLOW_THRESHOLD'),
+
+ // Collect only slow requests
+ 'slow_only' => env('CLOCKWORK_REQUESTS_SLOW_ONLY', false),
+
+ // Sample the collected requests (e.g. set to 100 to collect only 1 in 100 requests)
+ 'sample' => env('CLOCKWORK_REQUESTS_SAMPLE', false),
+
+ // List of URIs that should not be collected
+ 'except' => [
+ '/horizon/.*', // Laravel Horizon requests
+ '/telescope/.*', // Laravel Telescope requests
+ '/_debugbar/.*', // Laravel DebugBar requests
+ ],
+
+ // List of URIs that should be collected, any other URI will not be collected if not empty
+ 'only' => [
+ // '/api/.*'
+ ],
+
+ // Don't collect OPTIONS requests, mostly used in the CSRF pre-flight requests and are rarely of interest
+ 'except_preflight' => env('CLOCKWORK_REQUESTS_EXCEPT_PREFLIGHT', true)
+ ],
+
+ /*
+ |------------------------------------------------------------------------------------------------------------------
+ | Artisan commands collection
+ |------------------------------------------------------------------------------------------------------------------
+ |
+ | Clockwork can collect data about executed artisan commands. Here you can enable and configure which commands
+ | should be collected.
+ |
+ */
+
+ 'artisan' => [
+ // Enable or disable collection of executed Artisan commands
+ 'collect' => env('CLOCKWORK_ARTISAN_COLLECT', false),
+
+ // List of commands that should not be collected (built-in commands are not collected by default)
+ 'except' => [
+ // 'inspire'
+ ],
+
+ // List of commands that should be collected, any other command will not be collected if not empty
+ 'only' => [
+ // 'inspire'
+ ],
+
+ // Enable or disable collection of command output
+ 'collect_output' => env('CLOCKWORK_ARTISAN_COLLECT_OUTPUT', false),
+
+ // Enable or disable collection of built-in Laravel commands
+ 'except_laravel_commands' => env('CLOCKWORK_ARTISAN_EXCEPT_LARAVEL_COMMANDS', true)
+ ],
+
+ /*
+ |------------------------------------------------------------------------------------------------------------------
+ | Queue jobs collection
+ |------------------------------------------------------------------------------------------------------------------
+ |
+ | Clockwork can collect data about executed queue jobs. Here you can enable and configure which queue jobs should
+ | be collected.
+ |
+ */
+
+ 'queue' => [
+ // Enable or disable collection of executed queue jobs
+ 'collect' => env('CLOCKWORK_QUEUE_COLLECT', false),
+
+ // List of queue jobs that should not be collected
+ 'except' => [
+ // App\Jobs\ExpensiveJob::class
+ ],
+
+ // List of queue jobs that should be collected, any other queue job will not be collected if not empty
+ 'only' => [
+ // App\Jobs\BuggyJob::class
+ ]
+ ],
+
+ /*
+ |------------------------------------------------------------------------------------------------------------------
+ | Tests collection
+ |------------------------------------------------------------------------------------------------------------------
+ |
+ | Clockwork can collect data about executed tests. Here you can enable and configure which tests should be
+ | collected.
+ |
+ */
+
+ 'tests' => [
+ // Enable or disable collection of ran tests
+ 'collect' => env('CLOCKWORK_TESTS_COLLECT', false),
+
+ // List of tests that should not be collected
+ 'except' => [
+ // Tests\Unit\ExampleTest::class
+ ]
+ ],
+
+ /*
+ |------------------------------------------------------------------------------------------------------------------
+ | Enable data collection when Clockwork is disabled
+ |------------------------------------------------------------------------------------------------------------------
+ |
+ | You can enable this setting to collect data even when Clockwork is disabled, e.g. for future analysis.
+ |
+ */
+
+ 'collect_data_always' => env('CLOCKWORK_COLLECT_DATA_ALWAYS', false),
+
+ /*
+ |------------------------------------------------------------------------------------------------------------------
+ | Metadata storage
+ |------------------------------------------------------------------------------------------------------------------
+ |
+ | Configure how is the metadata collected by Clockwork stored. Two options are available:
+ | - files - A simple fast storage implementation storing data in one-per-request files.
+ | - sql - Stores requests in a sql database. Supports MySQL, PostgreSQL and SQLite. Requires PDO.
+ |
+ */
+
+ 'storage' => env('CLOCKWORK_STORAGE', 'files'),
+
+ // Path where the Clockwork metadata is stored
+ 'storage_files_path' => env('CLOCKWORK_STORAGE_FILES_PATH', storage_path('clockwork')),
+
+ // Compress the metadata files using gzip, trading a little bit of performance for lower disk usage
+ 'storage_files_compress' => env('CLOCKWORK_STORAGE_FILES_COMPRESS', false),
+
+ // SQL database to use, can be a name of database configured in database.php or a path to a SQLite file
+ 'storage_sql_database' => env('CLOCKWORK_STORAGE_SQL_DATABASE', storage_path('clockwork.sqlite')),
+
+ // SQL table name to use, the table is automatically created and updated when needed
+ 'storage_sql_table' => env('CLOCKWORK_STORAGE_SQL_TABLE', 'clockwork'),
+
+ // Maximum lifetime of collected metadata in minutes, older requests will automatically be deleted, false to disable
+ 'storage_expiration' => env('CLOCKWORK_STORAGE_EXPIRATION', 60 * 24 * 7),
+
+ /*
+ |------------------------------------------------------------------------------------------------------------------
+ | Authentication
+ |------------------------------------------------------------------------------------------------------------------
+ |
+ | Clockwork can be configured to require authentication before allowing access to the collected data. This might be
+ | useful when the application is publicly accessible. Setting to true will enable a simple authentication with a
+ | pre-configured password. You can also pass a class name of a custom implementation.
+ |
+ */
+
+ 'authentication' => env('CLOCKWORK_AUTHENTICATION', false),
+
+ // Password for the simple authentication
+ 'authentication_password' => env('CLOCKWORK_AUTHENTICATION_PASSWORD', 'VerySecretPassword'),
+
+ /*
+ |------------------------------------------------------------------------------------------------------------------
+ | Stack traces collection
+ |------------------------------------------------------------------------------------------------------------------
+ |
+ | Clockwork can collect stack traces for log messages and certain data like database queries. Here you can set
+ | whether to collect stack traces, limit the number of collected frames and set further configuration. Collecting
+ | long stack traces considerably increases metadata size.
+ |
+ */
+
+ 'stack_traces' => [
+ // Enable or disable collecting of stack traces
+ 'enabled' => env('CLOCKWORK_STACK_TRACES_ENABLED', true),
+
+ // Limit the number of frames to be collected
+ 'limit' => env('CLOCKWORK_STACK_TRACES_LIMIT', 10),
+
+ // List of vendor names to skip when determining caller, common vendors are automatically added
+ 'skip_vendors' => [
+ // 'phpunit'
+ ],
+
+ // List of namespaces to skip when determining caller
+ 'skip_namespaces' => [
+ // 'Laravel'
+ ],
+
+ // List of class names to skip when determining caller
+ 'skip_classes' => [
+ // App\CustomLog::class
+ ]
+
+ ],
+
+ /*
+ |------------------------------------------------------------------------------------------------------------------
+ | Serialization
+ |------------------------------------------------------------------------------------------------------------------
+ |
+ | Clockwork serializes the collected data to json for storage and transfer. Here you can configure certain aspects
+ | of serialization. Serialization has a large effect on the cpu time and memory usage.
+ |
+ */
+
+ // Maximum depth of serialized multi-level arrays and objects
+ 'serialization_depth' => env('CLOCKWORK_SERIALIZATION_DEPTH', 10),
+
+ // A list of classes that will never be serialized (e.g. a common service container class)
+ 'serialization_blackbox' => [
+ \Illuminate\Container\Container::class,
+ \Illuminate\Foundation\Application::class,
+ \Laravel\Lumen\Application::class
+ ],
+
+ /*
+ |------------------------------------------------------------------------------------------------------------------
+ | Register helpers
+ |------------------------------------------------------------------------------------------------------------------
+ |
+ | Clockwork comes with a "clock" global helper function. You can use this helper to quickly log something and to
+ | access the Clockwork instance.
+ |
+ */
+
+ 'register_helpers' => env('CLOCKWORK_REGISTER_HELPERS', true),
+
+ /*
+ |------------------------------------------------------------------------------------------------------------------
+ | Send headers for AJAX request
+ |------------------------------------------------------------------------------------------------------------------
+ |
+ | When trying to collect data, the AJAX method can sometimes fail if it is missing required headers. For example, an
+ | API might require a version number using Accept headers to route the HTTP request to the correct codebase.
+ |
+ */
+
+ 'headers' => [
+ // 'Accept' => 'application/vnd.com.whatever.v1+json',
+ ],
+
+ /*
+ |------------------------------------------------------------------------------------------------------------------
+ | Server timing
+ |------------------------------------------------------------------------------------------------------------------
+ |
+ | Clockwork supports the W3C Server Timing specification, which allows for collecting a simple performance metrics
+ | in a cross-browser way. E.g. in Chrome, your app, database and timeline event timings will be shown in the Dev
+ | Tools network tab. This setting specifies the max number of timeline events that will be sent. Setting to false
+ | will disable the feature.
+ |
+ */
+
+ 'server_timing' => env('CLOCKWORK_SERVER_TIMING', 10)
+
+];
diff --git a/config/querydetector.php b/config/querydetector.php
new file mode 100644
index 000000000..03f5ec7b0
--- /dev/null
+++ b/config/querydetector.php
@@ -0,0 +1,69 @@
+ env('QUERY_DETECTOR_ENABLED', null),
+
+ /*
+ * Threshold level for the N+1 query detection. If a relation query will be
+ * executed more then this amount, the detector will notify you about it.
+ */
+ 'threshold' => (int) env('QUERY_DETECTOR_THRESHOLD', 1),
+
+ /*
+ * Here you can whitelist model relations.
+ *
+ * Right now, you need to define the model relation both as the class name and the attribute name on the model.
+ * So if an "Author" model would have a "posts" relation that points to a "Post" class, you need to add both
+ * the "posts" attribute and the "Post::class", since the relation can get resolved in multiple ways.
+ */
+ 'except' => [
+ //Author::class => [
+ // Post::class,
+ // 'posts',
+ //]
+ ],
+
+ /*
+ * Here you can set a specific log channel to write to
+ * in case you are trying to isolate queries or have a lot
+ * going on in the laravel.log. Defaults to laravel.log though.
+ */
+ 'log_channel' => env('QUERY_DETECTOR_LOG_CHANNEL', 'daily'),
+
+ /*
+ * Define the output format that you want to use. Multiple classes are supported.
+ * Available options are:
+ *
+ * Alert:
+ * Displays an alert on the website
+ * \BeyondCode\QueryDetector\Outputs\Alert::class
+ *
+ * Console:
+ * Writes the N+1 queries into your browsers console log
+ * \BeyondCode\QueryDetector\Outputs\Console::class
+ *
+ * Clockwork: (make sure you have the itsgoingd/clockwork package installed)
+ * Writes the N+1 queries warnings to Clockwork log
+ * \BeyondCode\QueryDetector\Outputs\Clockwork::class
+ *
+ * Debugbar: (make sure you have the barryvdh/laravel-debugbar package installed)
+ * Writes the N+1 queries into a custom messages collector of Debugbar
+ * \BeyondCode\QueryDetector\Outputs\Debugbar::class
+ *
+ * JSON:
+ * Writes the N+1 queries into the response body of your JSON responses
+ * \BeyondCode\QueryDetector\Outputs\Json::class
+ *
+ * Log:
+ * Writes the N+1 queries into the Laravel.log file
+ * \BeyondCode\QueryDetector\Outputs\Log::class
+ */
+ 'output' => [
+ \BeyondCode\QueryDetector\Outputs\Alert::class,
+ \BeyondCode\QueryDetector\Outputs\Log::class,
+ ]
+];
diff --git a/lang/en/lang.php b/lang/en/lang.php
index bb911e346..b84f6a746 100755
--- a/lang/en/lang.php
+++ b/lang/en/lang.php
@@ -1415,6 +1415,7 @@ return [
*/
'error-debug' => 'Error logs and debugging',
'debug-options' => 'Debugging options',
+ 'clock-work' =>'Clock work',
'view-logs' => 'View error logs',
'not-authorised-error-debug' => 'You are not authorised to access the URL',
'error-debug-settings' => 'Error and debugging settings',
diff --git a/resources/views/themes/default1/admin/helpdesk/setting.blade.php b/resources/views/themes/default1/admin/helpdesk/setting.blade.php
index 30385c666..009f5e80a 100644
--- a/resources/views/themes/default1/admin/helpdesk/setting.blade.php
+++ b/resources/views/themes/default1/admin/helpdesk/setting.blade.php
@@ -540,13 +540,27 @@
{!! Lang::get('lang.debug-options') !!}
+
+ @if(Config::get('app.debug'))
+
+
+
+
+
{!!Lang::get('lang.clock-work')!!}
+
+
+ @endif
+
-
-
-
-
-
+
+
diff --git a/vendor/barryvdh/laravel-debugbar/composer.json b/vendor/barryvdh/laravel-debugbar/composer.json
index b911a5e3d..4312ed4ab 100644
--- a/vendor/barryvdh/laravel-debugbar/composer.json
+++ b/vendor/barryvdh/laravel-debugbar/composer.json
@@ -10,17 +10,17 @@
}
],
"require": {
- "php": ">=7.2.5",
+ "php": "^8.0",
"maximebf/debugbar": "^1.17.2",
- "illuminate/routing": "^7|^8|^9",
- "illuminate/session": "^7|^8|^9",
- "illuminate/support": "^7|^8|^9",
- "symfony/finder": "^5|^6"
+ "illuminate/routing": "^9|^10",
+ "illuminate/session": "^9|^10",
+ "illuminate/support": "^9|^10",
+ "symfony/finder": "^6"
},
"require-dev": {
"mockery/mockery": "^1.3.3",
- "orchestra/testbench-dusk": "^5|^6|^7",
- "phpunit/phpunit": "^8.5|^9.0",
+ "orchestra/testbench-dusk": "^5|^6|^7|^8",
+ "phpunit/phpunit": "^8.5.30|^9.0",
"squizlabs/php_codesniffer": "^3.5"
},
"autoload": {
@@ -52,8 +52,8 @@
}
},
"scripts": {
- "check-style": "phpcs -p --standard=PSR12 config/ src/ tests/",
- "fix-style": "phpcbf -p --standard=PSR12 config/ src/ tests/",
+ "check-style": "phpcs -p --standard=PSR12 config/ src/ tests/ --ignore=src/Resources/* ",
+ "fix-style": "phpcbf -p --standard=PSR12 config/ src/ tests/ --ignore=src/Resources*",
"test": "phpunit"
}
}
diff --git a/vendor/barryvdh/laravel-debugbar/config/debugbar.php b/vendor/barryvdh/laravel-debugbar/config/debugbar.php
index fe3b192d7..5c4643cf7 100644
--- a/vendor/barryvdh/laravel-debugbar/config/debugbar.php
+++ b/vendor/barryvdh/laravel-debugbar/config/debugbar.php
@@ -92,7 +92,7 @@ return [
| Vendor files are included by default, but can be set to false.
| This can also be set to 'js' or 'css', to only include javascript or css vendor files.
| Vendor files are for css: font-awesome (including fonts) and highlight.js (css files)
- | and for js: jquery and and highlight.js
+ | and for js: jquery and highlight.js
| So if you want syntax highlighting, set it to true.
| jQuery is set to not conflict with existing jQuery scripts.
|
@@ -198,7 +198,8 @@ return [
'types' => ['SELECT'], // Deprecated setting, is always only SELECT
],
'hints' => false, // Show hints for common mistakes
- 'show_copy' => false, // Show copy button next to the query
+ 'show_copy' => false, // Show copy button next to the query,
+ 'slow_threshold' => false, // Only track queries that last longer than this time in ms
],
'mail' => [
'full_log' => false,
@@ -206,6 +207,7 @@ return [
'views' => [
'timeline' => false, // Add the views to the timeline (Experimental)
'data' => false, //Note: Can slow down the application, because the data can be quite large..
+ 'exclude_paths' => [], // Add the paths which you don't want to appear in the views
],
'route' => [
'label' => true, // show complete route on bar
diff --git a/vendor/barryvdh/laravel-debugbar/readme.md b/vendor/barryvdh/laravel-debugbar/readme.md
index 54eaafba1..5bac5ccd9 100644
--- a/vendor/barryvdh/laravel-debugbar/readme.md
+++ b/vendor/barryvdh/laravel-debugbar/readme.md
@@ -1,4 +1,4 @@
-## Laravel Debugbar
+## Debugbar for Laravel

[](http://choosealicense.com/licenses/mit/)
[](https://packagist.org/packages/barryvdh/laravel-debugbar)
diff --git a/vendor/barryvdh/laravel-debugbar/src/DataCollector/QueryCollector.php b/vendor/barryvdh/laravel-debugbar/src/DataCollector/QueryCollector.php
index fbeaf81b5..f07aa3bf7 100644
--- a/vendor/barryvdh/laravel-debugbar/src/DataCollector/QueryCollector.php
+++ b/vendor/barryvdh/laravel-debugbar/src/DataCollector/QueryCollector.php
@@ -134,7 +134,7 @@ class QueryCollector extends PDOCollector
$pdo = null;
try {
$pdo = $connection->getPdo();
- } catch (\Exception $e) {
+ } catch (\Throwable $e) {
// ignore error for non-pdo laravel drivers
}
$bindings = $connection->prepareBindings($bindings);
@@ -511,6 +511,41 @@ class QueryCollector extends PDOCollector
'type' => 'explain',
];
}
+ } elseif ($query['driver'] === 'sqlite') {
+ $vmi = '
';
+ $vmi .= "
+ Address |
+ Opcode |
+ P1 |
+ P2 |
+ P3 |
+ P4 |
+ P5 |
+ Comment |
+
";
+
+ foreach ($query['explain'] as $explain) {
+ $vmi .= "
+ {$explain->addr} |
+ {$explain->opcode} |
+ {$explain->p1} |
+ {$explain->p2} |
+ {$explain->p3} |
+ {$explain->p4} |
+ {$explain->p5} |
+ {$explain->comment} |
+
";
+ }
+
+ $vmi .= '
';
+
+ $statements[] = [
+ 'sql' => " - EXPLAIN:",
+ 'type' => 'explain',
+ 'params' => [
+ 'Virtual Machine Instructions' => $vmi,
+ ]
+ ];
} else {
foreach ($query['explain'] as $explain) {
$statements[] = [
diff --git a/vendor/barryvdh/laravel-debugbar/src/DataCollector/ViewCollector.php b/vendor/barryvdh/laravel-debugbar/src/DataCollector/ViewCollector.php
index 7a1b0c577..b0ae1baa4 100644
--- a/vendor/barryvdh/laravel-debugbar/src/DataCollector/ViewCollector.php
+++ b/vendor/barryvdh/laravel-debugbar/src/DataCollector/ViewCollector.php
@@ -5,24 +5,51 @@ namespace Barryvdh\Debugbar\DataCollector;
use Barryvdh\Debugbar\DataFormatter\SimpleFormatter;
use DebugBar\Bridge\Twig\TwigCollector;
use Illuminate\View\View;
-use Symfony\Component\VarDumper\Cloner\VarCloner;
+use InvalidArgumentException;
class ViewCollector extends TwigCollector
{
+ protected $name;
protected $templates = [];
protected $collect_data;
+ protected $exclude_paths;
+
+ /**
+ * A list of known editor strings.
+ *
+ * @var array
+ */
+ protected $editors = [
+ 'sublime' => 'subl://open?url=file://%file&line=%line',
+ 'textmate' => 'txmt://open?url=file://%file&line=%line',
+ 'emacs' => 'emacs://open?url=file://%file&line=%line',
+ 'macvim' => 'mvim://open/?url=file://%file&line=%line',
+ 'phpstorm' => 'phpstorm://open?file=%file&line=%line',
+ 'idea' => 'idea://open?file=%file&line=%line',
+ 'vscode' => 'vscode://file/%file:%line',
+ 'vscode-insiders' => 'vscode-insiders://file/%file:%line',
+ 'vscode-remote' => 'vscode://vscode-remote/%file:%line',
+ 'vscode-insiders-remote' => 'vscode-insiders://vscode-remote/%file:%line',
+ 'vscodium' => 'vscodium://file/%file:%line',
+ 'nova' => 'nova://core/open/file?filename=%file&line=%line',
+ 'xdebug' => 'xdebug://%file@%line',
+ 'atom' => 'atom://core/open/file?filename=%file&line=%line',
+ 'espresso' => 'x-espresso://open?filepath=%file&lines=%line',
+ 'netbeans' => 'netbeans://open/?f=%file:%line',
+ ];
/**
* Create a ViewCollector
*
* @param bool $collectData Collects view data when tru
+ * @param string[] $excludePaths Paths to exclude from collection
*/
- public function __construct($collectData = true)
+ public function __construct($collectData = true, $excludePaths = [])
{
$this->setDataFormatter(new SimpleFormatter());
$this->collect_data = $collectData;
- $this->name = 'views';
$this->templates = [];
+ $this->exclude_paths = $excludePaths;
}
public function getName()
@@ -35,7 +62,7 @@ class ViewCollector extends TwigCollector
return [
'views' => [
'icon' => 'leaf',
- 'widget' => 'PhpDebugBar.Widgets.TemplatesWidget',
+ 'widget' => 'PhpDebugBar.Widgets.LaravelViewTemplatesWidget',
'map' => 'views',
'default' => '[]'
],
@@ -46,6 +73,36 @@ class ViewCollector extends TwigCollector
];
}
+ /**
+ * Get the editor href for a given file and line, if available.
+ *
+ * @param string $filePath
+ * @param int $line
+ *
+ * @throws InvalidArgumentException If editor resolver does not return a string
+ *
+ * @return null|string
+ */
+ protected function getEditorHref($filePath, $line)
+ {
+ if (empty(config('debugbar.editor'))) {
+ return null;
+ }
+
+ if (empty($this->editors[config('debugbar.editor')])) {
+ throw new InvalidArgumentException(
+ 'Unknown editor identifier: ' . config('debugbar.editor') . '. Known editors:' .
+ implode(', ', array_keys($this->editors))
+ );
+ }
+
+ $filePath = $this->replaceSitesPath($filePath);
+
+ $url = str_replace(['%file', '%line'], [$filePath, $line], $this->editors[config('debugbar.editor')]);
+
+ return $url;
+ }
+
/**
* Add a View instance to the Collector
*
@@ -71,6 +128,12 @@ class ViewCollector extends TwigCollector
$path = '';
}
+ foreach ($this->exclude_paths as $excludePath) {
+ if (strpos($path, $excludePath) !== false) {
+ return;
+ }
+ }
+
if (!$this->collect_data) {
$params = array_keys($view->getData());
} else {
@@ -86,6 +149,7 @@ class ViewCollector extends TwigCollector
'param_count' => count($params),
'params' => $params,
'type' => $type,
+ 'editorLink' => $this->getEditorHref($view->getPath(), 0),
];
if ($this->getXdebugLink($path)) {
@@ -104,4 +168,16 @@ class ViewCollector extends TwigCollector
'templates' => $templates,
];
}
+
+ /**
+ * Replace remote path
+ *
+ * @param string $filePath
+ *
+ * @return string
+ */
+ protected function replaceSitesPath($filePath)
+ {
+ return str_replace(config('debugbar.remote_sites_path'), config('debugbar.local_sites_path'), $filePath);
+ }
}
diff --git a/vendor/barryvdh/laravel-debugbar/src/DataFormatter/QueryFormatter.php b/vendor/barryvdh/laravel-debugbar/src/DataFormatter/QueryFormatter.php
index f8574f5d6..dc49853e6 100644
--- a/vendor/barryvdh/laravel-debugbar/src/DataFormatter/QueryFormatter.php
+++ b/vendor/barryvdh/laravel-debugbar/src/DataFormatter/QueryFormatter.php
@@ -4,6 +4,7 @@ namespace Barryvdh\Debugbar\DataFormatter;
use DebugBar\DataFormatter\DataFormatter;
+#[\AllowDynamicProperties]
class QueryFormatter extends DataFormatter
{
/**
diff --git a/vendor/barryvdh/laravel-debugbar/src/DataFormatter/SimpleFormatter.php b/vendor/barryvdh/laravel-debugbar/src/DataFormatter/SimpleFormatter.php
index 9825e9133..369e1be3f 100644
--- a/vendor/barryvdh/laravel-debugbar/src/DataFormatter/SimpleFormatter.php
+++ b/vendor/barryvdh/laravel-debugbar/src/DataFormatter/SimpleFormatter.php
@@ -9,6 +9,7 @@ use DebugBar\DataFormatter\DataFormatter;
*
* @see https://github.com/symfony/symfony/blob/v3.4.4/src/Symfony/Component/HttpKernel/DataCollector/Util/ValueExporter.php
*/
+#[\AllowDynamicProperties]
class SimpleFormatter extends DataFormatter
{
/**
diff --git a/vendor/barryvdh/laravel-debugbar/src/JavascriptRenderer.php b/vendor/barryvdh/laravel-debugbar/src/JavascriptRenderer.php
index 428b15a9d..9c967909e 100644
--- a/vendor/barryvdh/laravel-debugbar/src/JavascriptRenderer.php
+++ b/vendor/barryvdh/laravel-debugbar/src/JavascriptRenderer.php
@@ -23,6 +23,7 @@ class JavascriptRenderer extends BaseJavascriptRenderer
$this->cssVendors['fontawesome'] = __DIR__ . '/Resources/vendor/font-awesome/style.css';
$this->jsFiles['laravel-sql'] = __DIR__ . '/Resources/sqlqueries/widget.js';
$this->jsFiles['laravel-cache'] = __DIR__ . '/Resources/cache/widget.js';
+ $this->jsFiles['laravel-view'] = __DIR__ . '/Resources/templates/widget.js';
$theme = config('debugbar.theme', 'auto');
switch ($theme) {
diff --git a/vendor/barryvdh/laravel-debugbar/src/LaravelDebugbar.php b/vendor/barryvdh/laravel-debugbar/src/LaravelDebugbar.php
index 1842aa5de..5cf221095 100644
--- a/vendor/barryvdh/laravel-debugbar/src/LaravelDebugbar.php
+++ b/vendor/barryvdh/laravel-debugbar/src/LaravelDebugbar.php
@@ -34,6 +34,7 @@ use DebugBar\DebugBar;
use DebugBar\Storage\PdoStorage;
use DebugBar\Storage\RedisStorage;
use Exception;
+use Throwable;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Session\SessionManager;
use Illuminate\Support\Str;
@@ -204,7 +205,8 @@ class LaravelDebugbar extends DebugBar
if ($this->shouldCollect('views', true) && isset($this->app['events'])) {
try {
$collectData = $this->app['config']->get('debugbar.options.views.data', true);
- $this->addCollector(new ViewCollector($collectData));
+ $excludePaths = $this->app['config']->get('debugbar.options.views.exclude_paths', []);
+ $this->addCollector(new ViewCollector($collectData, $excludePaths));
$this->app['events']->listen(
'composing:*',
function ($view, $data = []) use ($debugbar) {
@@ -258,7 +260,7 @@ class LaravelDebugbar extends DebugBar
try {
$logMessage = (string) $message;
if (mb_check_encoding($logMessage, 'UTF-8')) {
- $logMessage .= (!empty($context) ? ' ' . json_encode($context) : '');
+ $logMessage .= (!empty($context) ? ' ' . json_encode($context, JSON_PRETTY_PRINT) : '');
} else {
$logMessage = "[INVALID UTF-8 DATA]";
}
@@ -635,7 +637,7 @@ class LaravelDebugbar extends DebugBar
/**
* Adds an exception to be profiled in the debug bar
*
- * @param Exception $e
+ * @param Throwable $e
*/
public function addThrowable($e)
{
diff --git a/vendor/barryvdh/laravel-debugbar/src/Resources/laravel-debugbar-dark-mode.css b/vendor/barryvdh/laravel-debugbar/src/Resources/laravel-debugbar-dark-mode.css
index 69baff9b9..50f7832d2 100644
--- a/vendor/barryvdh/laravel-debugbar/src/Resources/laravel-debugbar-dark-mode.css
+++ b/vendor/barryvdh/laravel-debugbar/src/Resources/laravel-debugbar-dark-mode.css
@@ -24,6 +24,8 @@ div.phpdebugbar-openhandler,
div.phpdebugbar div.phpdebugbar-header > div > *,
div.phpdebugbar ul.phpdebugbar-widgets-timeline li span.phpdebugbar-widgets-label,
div.phpdebugbar ul.phpdebugbar-widgets-timeline li span.phpdebugbar-widgets-collector,
+div.phpdebugbar ul.phpdebugbar-widgets-list li.phpdebugbar-widgets-list-item,
+div.phpdebugbar ul.phpdebugbar-widgets-list li span.phpdebugbar-widgets-label,
div.phpdebugbar code.phpdebugbar-widgets-sql span.hljs-keyword,
div.phpdebugbar-openhandler .phpdebugbar-openhandler-header,
div.phpdebugbar-openhandler .phpdebugbar-openhandler-header a {
diff --git a/vendor/barryvdh/laravel-debugbar/src/Resources/laravel-debugbar.css b/vendor/barryvdh/laravel-debugbar/src/Resources/laravel-debugbar.css
index 424c6ad49..346e55cc0 100644
--- a/vendor/barryvdh/laravel-debugbar/src/Resources/laravel-debugbar.css
+++ b/vendor/barryvdh/laravel-debugbar/src/Resources/laravel-debugbar.css
@@ -13,6 +13,7 @@ div.phpdebugbar {
div.phpdebugbar * {
direction: ltr;
+ font-size: initial;
text-align: left;
}
diff --git a/vendor/barryvdh/laravel-debugbar/src/Resources/templates/widget.js b/vendor/barryvdh/laravel-debugbar/src/Resources/templates/widget.js
new file mode 100644
index 000000000..bb39188b5
--- /dev/null
+++ b/vendor/barryvdh/laravel-debugbar/src/Resources/templates/widget.js
@@ -0,0 +1,98 @@
+(function($) {
+
+ var csscls = PhpDebugBar.utils.makecsscls('phpdebugbar-widgets-');
+
+ /**
+ * Widget for the displaying templates data
+ *
+ * Options:
+ * - data
+ */
+ var TemplatesWidget = PhpDebugBar.Widgets.LaravelViewTemplatesWidget = PhpDebugBar.Widget.extend({
+
+ className: csscls('templates'),
+
+ render: function() {
+ this.$status = $('
').addClass(csscls('status')).appendTo(this.$el);
+
+ this.$list = new PhpDebugBar.Widgets.ListWidget({ itemRenderer: function(li, tpl) {
+ $('
').addClass(csscls('name')).text(tpl.name).appendTo(li);
+
+ if (typeof tpl.editorLink !== 'undefined' && tpl.editorLink !== null) {
+ $('
')
+ .addClass(csscls('editor-link'))
+ .on('click', function (event) {
+ event.stopPropagation();
+ })
+ .appendTo(li);
+ }
+ if (typeof tpl.xdebug_link !== 'undefined' && tpl.xdebug_link !== null) {
+ if (tpl.xdebug_link.ajax) {
+ $('
').on('click', function () {
+ $.ajax(tpl.xdebug_link.url);
+ }).addClass(csscls('editor-link')).appendTo(li);
+ } else {
+ $('
').addClass(csscls('editor-link')).appendTo(li);
+ }
+ }
+ if (tpl.render_time_str) {
+ $('
').addClass(csscls('render-time')).text(tpl.render_time_str).appendTo(li);
+ }
+ if (tpl.memory_str) {
+ $('
').addClass(csscls('memory')).text(tpl.memory_str).appendTo(li);
+ }
+ if (typeof(tpl.param_count) != 'undefined') {
+ $('
').addClass(csscls('param-count')).text(tpl.param_count).appendTo(li);
+ }
+ if (typeof(tpl.type) != 'undefined' && tpl.type) {
+ $('
').addClass(csscls('type')).text(tpl.type).appendTo(li);
+ }
+ if (tpl.params && !$.isEmptyObject(tpl.params)) {
+ var table = $('
').addClass(csscls('params')).appendTo(li);
+ for (var key in tpl.params) {
+ if (typeof tpl.params[key] !== 'function') {
+ table.append('
' + key + ' | ' + tpl.params[key] + '
|
');
+ }
+ }
+ li.css('cursor', 'pointer').click(function() {
+ if (table.is(':visible')) {
+ table.hide();
+ } else {
+ table.show();
+ }
+ });
+ }
+ }});
+ this.$list.$el.appendTo(this.$el);
+ this.$callgraph = $('
').addClass(csscls('callgraph')).appendTo(this.$el);
+
+ this.bindAttr('data', function(data) {
+ this.$list.set('data', data.templates);
+ this.$status.empty();
+ this.$callgraph.empty();
+
+ var sentence = data.sentence || "templates were rendered";
+ $('
').text(data.nb_templates + " " + sentence).appendTo(this.$status);
+
+ if (data.accumulated_render_time_str) {
+ this.$status.append($('
').addClass(csscls('render-time')).text(data.accumulated_render_time_str));
+ }
+ if (data.memory_usage_str) {
+ this.$status.append($('
').addClass(csscls('memory')).text(data.memory_usage_str));
+ }
+ if (data.nb_blocks > 0) {
+ $('
').text(data.nb_blocks + " blocks were rendered").appendTo(this.$status);
+ }
+ if (data.nb_macros > 0) {
+ $('
').text(data.nb_macros + " macros were rendered").appendTo(this.$status);
+ }
+ if (typeof data.callgraph !== 'undefined') {
+ this.$callgraph.html(data.callgraph);
+ }
+ });
+ }
+
+ });
+
+})(PhpDebugBar.$);
diff --git a/vendor/barryvdh/laravel-debugbar/src/Twig/Extension/Debug.php b/vendor/barryvdh/laravel-debugbar/src/Twig/Extension/Debug.php
index 42bc2cb32..a70b69a4f 100644
--- a/vendor/barryvdh/laravel-debugbar/src/Twig/Extension/Debug.php
+++ b/vendor/barryvdh/laravel-debugbar/src/Twig/Extension/Debug.php
@@ -10,7 +10,7 @@ use Twig_SimpleFunction;
/**
* Access Laravels auth class in your Twig templates.
*/
-class Debug extends Twig_Extension
+class Debug extends Extension
{
/**
* @var \Barryvdh\Debugbar\LaravelDebugbar
@@ -44,8 +44,15 @@ class Debug extends Twig_Extension
*/
public function getFunctions()
{
+ // Maintain compatibility with Twig 2 and 3.
+ $simpleFunction = 'Twig_SimpleFunction';
+
+ if (!class_exists($simpleFunction)) {
+ $simpleFunction = '\Twig\TwigFunction';
+ }
+
return [
- new Twig_SimpleFunction(
+ new $simpleFunction(
'debug',
[$this, 'debug'],
['needs_context' => true, 'needs_environment' => true]
@@ -57,10 +64,10 @@ class Debug extends Twig_Extension
* Based on Twig_Extension_Debug / twig_var_dump
* (c) 2011 Fabien Potencier
*
- * @param Twig_Environment $env
+ * @param \Twig_Environment|\Twig\Environment $env
* @param $context
*/
- public function debug(Twig_Environment $env, $context)
+ public function debug($env, $context)
{
if (!$env->isDebug() || !$this->debugbar) {
return;
diff --git a/vendor/barryvdh/laravel-debugbar/src/Twig/Extension/Dump.php b/vendor/barryvdh/laravel-debugbar/src/Twig/Extension/Dump.php
index b42fafa42..edd17ba03 100644
--- a/vendor/barryvdh/laravel-debugbar/src/Twig/Extension/Dump.php
+++ b/vendor/barryvdh/laravel-debugbar/src/Twig/Extension/Dump.php
@@ -3,14 +3,11 @@
namespace Barryvdh\Debugbar\Twig\Extension;
use DebugBar\DataFormatter\DataFormatterInterface;
-use Twig_Environment;
-use Twig_Extension;
-use Twig_SimpleFunction;
/**
* Dump variables using the DataFormatter
*/
-class Dump extends Twig_Extension
+class Dump extends Extension
{
/**
* @var \DebugBar\DataFormatter\DataFormatter
@@ -40,8 +37,15 @@ class Dump extends Twig_Extension
*/
public function getFunctions()
{
+ // Maintain compatibility with Twig 2 and 3.
+ $simpleFunction = '\Twig_SimpleFunction';
+
+ if (!class_exists($simpleFunction)) {
+ $simpleFunction = '\Twig\TwigFunction';
+ }
+
return [
- new Twig_SimpleFunction(
+ new $simpleFunction(
'dump',
[$this, 'dump'],
['is_safe' => ['html'], 'needs_context' => true, 'needs_environment' => true]
@@ -53,12 +57,12 @@ class Dump extends Twig_Extension
* Based on Twig_Extension_Debug / twig_var_dump
* (c) 2011 Fabien Potencier
*
- * @param Twig_Environment $env
+ * @param \Twig_Environment|\Twig\Environment $env
* @param $context
*
* @return string
*/
- public function dump(Twig_Environment $env, $context)
+ public function dump($env, $context)
{
$output = '';
diff --git a/vendor/barryvdh/laravel-debugbar/src/Twig/Extension/Extension.php b/vendor/barryvdh/laravel-debugbar/src/Twig/Extension/Extension.php
new file mode 100644
index 000000000..dda2a6171
--- /dev/null
+++ b/vendor/barryvdh/laravel-debugbar/src/Twig/Extension/Extension.php
@@ -0,0 +1,14 @@
+
*/
-class StopwatchNode extends \Twig_Node
+class StopwatchNode extends Node
{
+ /**
+ * @param \Twig_NodeInterface|\Twig\Node\Node $name
+ * @param $body
+ * @param \Twig_Node_Expression_AssignName|\Twig\Node\Expression\AssignNameExpression $var
+ * @param $lineno
+ * @param $tag
+ */
public function __construct(
- \Twig_NodeInterface $name,
+ $name,
$body,
- \Twig_Node_Expression_AssignName $var,
+ $var,
$lineno = 0,
$tag = null
) {
parent::__construct(['body' => $body, 'name' => $name, 'var' => $var], [], $lineno, $tag);
}
- public function compile(\Twig_Compiler $compiler)
+ /**
+ * @param \Twig_Compiler|\Twig\Compiler $env
+ * @return void
+ */
+ public function compile($compiler)
{
+ // Maintain compatibility with Twig 2 and 3.
+ $extension = \Barryvdh\Debugbar\Twig\Extension\Stopwatch::class;
+ if (class_exists('\Twig_Node')) {
+ $extension = 'stopwatch';
+ }
+
$compiler
->addDebugInfo($this)
->write('')
@@ -28,11 +45,11 @@ class StopwatchNode extends \Twig_Node
->raw(' = ')
->subcompile($this->getNode('name'))
->write(";\n")
- ->write("\$this->env->getExtension('stopwatch')->getDebugbar()->startMeasure(")
+ ->write(sprintf("\$this->env->getExtension('%s')->getDebugbar()->startMeasure(", $extension))
->subcompile($this->getNode('var'))
->raw(");\n")
->subcompile($this->getNode('body'))
- ->write("\$this->env->getExtension('stopwatch')->getDebugbar()->stopMeasure(")
+ ->write(sprintf("\$this->env->getExtension('%s')->getDebugbar()->stopMeasure(", $extension))
->subcompile($this->getNode('var'))
->raw(");\n");
}
diff --git a/vendor/barryvdh/laravel-debugbar/src/Twig/TokenParser/StopwatchTokenParser.php b/vendor/barryvdh/laravel-debugbar/src/Twig/TokenParser/StopwatchTokenParser.php
index cb197a208..896af4992 100644
--- a/vendor/barryvdh/laravel-debugbar/src/Twig/TokenParser/StopwatchTokenParser.php
+++ b/vendor/barryvdh/laravel-debugbar/src/Twig/TokenParser/StopwatchTokenParser.php
@@ -9,7 +9,7 @@ use Barryvdh\Debugbar\Twig\Node\StopwatchNode;
*
* @author Wouter J
*/
-class StopwatchTokenParser extends \Twig_TokenParser
+class StopwatchTokenParser extends TokenParser
{
protected $debugbarAvailable;
@@ -18,7 +18,10 @@ class StopwatchTokenParser extends \Twig_TokenParser
$this->debugbarAvailable = $debugbarAvailable;
}
- public function parse(\Twig_Token $token)
+ /**
+ * @param \Twig_Token|\Twig\Token $token
+ */
+ public function parse($token)
{
$lineno = $token->getLine();
$stream = $this->parser->getStream();
@@ -26,17 +29,31 @@ class StopwatchTokenParser extends \Twig_TokenParser
// {% stopwatch 'bar' %}
$name = $this->parser->getExpressionParser()->parseExpression();
- $stream->expect(\Twig_Token::BLOCK_END_TYPE);
+ // Maintain compatibility with Twig 2 and 3.
+ if (class_exists("\Twig_Token")) {
+ $blockEndType = \Twig_Token::BLOCK_END_TYPE;
+ } else {
+ $blockEndType = \Twig\Token::BLOCK_END_TYPE;
+ }
+
+ $stream->expect($blockEndType);
// {% endstopwatch %}
$body = $this->parser->subparse([$this, 'decideStopwatchEnd'], true);
- $stream->expect(\Twig_Token::BLOCK_END_TYPE);
+ $stream->expect($blockEndType);
+
+ // Maintain compatibility with Twig 2 and 3.
+ if (class_exists("\Twig_Node_Expression_AssignName")) {
+ $assignNameExpression = new \Twig_Node_Expression_AssignName($this->parser->getVarName(), $token->getLine());
+ } else {
+ $assignNameExpression = new \Twig\Node\Expression\AssignNameExpression($this->parser->getVarName(), $token->getLine());
+ }
if ($this->debugbarAvailable) {
return new StopwatchNode(
$name,
$body,
- new \Twig_Node_Expression_AssignName($this->parser->getVarName(), $token->getLine()),
+ $assignNameExpression,
$lineno,
$this->getTag()
);
@@ -50,7 +67,10 @@ class StopwatchTokenParser extends \Twig_TokenParser
return 'stopwatch';
}
- public function decideStopwatchEnd(\Twig_Token $token)
+ /**
+ * @param \Twig_Token|\Twig\Token $token
+ */
+ public function decideStopwatchEnd($token)
{
return $token->test('endstopwatch');
}
diff --git a/vendor/barryvdh/laravel-debugbar/src/Twig/TokenParser/TokenParser.php b/vendor/barryvdh/laravel-debugbar/src/Twig/TokenParser/TokenParser.php
new file mode 100644
index 000000000..2ff179628
--- /dev/null
+++ b/vendor/barryvdh/laravel-debugbar/src/Twig/TokenParser/TokenParser.php
@@ -0,0 +1,14 @@
+
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/vendor/beyondcode/laravel-query-detector/README.md b/vendor/beyondcode/laravel-query-detector/README.md
new file mode 100644
index 000000000..e356d240a
--- /dev/null
+++ b/vendor/beyondcode/laravel-query-detector/README.md
@@ -0,0 +1,53 @@
+# Laravel N+1 Query Detector
+
+[](https://packagist.org/packages/beyondcode/laravel-query-detector)
+[](https://travis-ci.org/beyondcode/laravel-query-detector)
+[](https://scrutinizer-ci.com/g/beyondcode/laravel-query-detector)
+[](https://packagist.org/packages/beyondcode/laravel-query-detector)
+
+The Laravel N+1 query detector helps you to increase your application's performance by reducing the number of queries it executes. This package monitors your queries in real-time, while you develop your application and notify you when you should add eager loading (N+1 queries).
+
+
+
+
+## Installation
+
+You can install the package via composer:
+
+```bash
+composer require beyondcode/laravel-query-detector --dev
+```
+
+The package will automatically register itself.
+
+## Documentation
+
+You can find the documentation on our [website](http://beyondco.de/docs/laravel-query-detector).
+
+
+### Testing
+
+``` bash
+composer test
+```
+
+### Changelog
+
+Please see [CHANGELOG](CHANGELOG.md) for more information what has changed recently.
+
+## Contributing
+
+Please see [CONTRIBUTING](CONTRIBUTING.md) for details.
+
+### Security
+
+If you discover any security related issues, please email marcel@beyondco.de instead of using the issue tracker.
+
+## Credits
+
+- [Marcel Pociot](https://github.com/mpociot)
+- [All Contributors](../../contributors)
+
+## License
+
+The MIT License (MIT). Please see [License File](LICENSE.md) for more information.
diff --git a/vendor/beyondcode/laravel-query-detector/composer.json b/vendor/beyondcode/laravel-query-detector/composer.json
new file mode 100644
index 000000000..23ff06e92
--- /dev/null
+++ b/vendor/beyondcode/laravel-query-detector/composer.json
@@ -0,0 +1,51 @@
+{
+ "name": "beyondcode/laravel-query-detector",
+ "description": "Laravel N+1 Query Detector",
+ "keywords": [
+ "beyondcode",
+ "laravel-query-detector"
+ ],
+ "homepage": "https://github.com/beyondcode/laravel-query-detector",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Marcel Pociot",
+ "email": "marcel@beyondco.de",
+ "homepage": "https://beyondcode.de",
+ "role": "Developer"
+ }
+ ],
+ "require": {
+ "php": "^7.1 || ^8.0",
+ "illuminate/support": "^5.5 || ^6.0 || ^7.0 || ^8.0 || ^9.0|^10.0"
+ },
+ "require-dev": {
+ "laravel/legacy-factories": "^1.0",
+ "orchestra/testbench": "^3.0 || ^4.0 || ^5.0 || ^6.0|^8.0",
+ "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0"
+ },
+ "autoload": {
+ "psr-4": {
+ "BeyondCode\\QueryDetector\\": "src"
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "BeyondCode\\QueryDetector\\Tests\\": "tests"
+ }
+ },
+ "scripts": {
+ "test": "vendor/bin/phpunit",
+ "test-coverage": "vendor/bin/phpunit --coverage-html coverage"
+ },
+ "config": {
+ "sort-packages": true
+ },
+ "extra": {
+ "laravel": {
+ "providers": [
+ "BeyondCode\\QueryDetector\\QueryDetectorServiceProvider"
+ ]
+ }
+ }
+}
diff --git a/vendor/beyondcode/laravel-query-detector/config/config.php b/vendor/beyondcode/laravel-query-detector/config/config.php
new file mode 100644
index 000000000..03f5ec7b0
--- /dev/null
+++ b/vendor/beyondcode/laravel-query-detector/config/config.php
@@ -0,0 +1,69 @@
+ env('QUERY_DETECTOR_ENABLED', null),
+
+ /*
+ * Threshold level for the N+1 query detection. If a relation query will be
+ * executed more then this amount, the detector will notify you about it.
+ */
+ 'threshold' => (int) env('QUERY_DETECTOR_THRESHOLD', 1),
+
+ /*
+ * Here you can whitelist model relations.
+ *
+ * Right now, you need to define the model relation both as the class name and the attribute name on the model.
+ * So if an "Author" model would have a "posts" relation that points to a "Post" class, you need to add both
+ * the "posts" attribute and the "Post::class", since the relation can get resolved in multiple ways.
+ */
+ 'except' => [
+ //Author::class => [
+ // Post::class,
+ // 'posts',
+ //]
+ ],
+
+ /*
+ * Here you can set a specific log channel to write to
+ * in case you are trying to isolate queries or have a lot
+ * going on in the laravel.log. Defaults to laravel.log though.
+ */
+ 'log_channel' => env('QUERY_DETECTOR_LOG_CHANNEL', 'daily'),
+
+ /*
+ * Define the output format that you want to use. Multiple classes are supported.
+ * Available options are:
+ *
+ * Alert:
+ * Displays an alert on the website
+ * \BeyondCode\QueryDetector\Outputs\Alert::class
+ *
+ * Console:
+ * Writes the N+1 queries into your browsers console log
+ * \BeyondCode\QueryDetector\Outputs\Console::class
+ *
+ * Clockwork: (make sure you have the itsgoingd/clockwork package installed)
+ * Writes the N+1 queries warnings to Clockwork log
+ * \BeyondCode\QueryDetector\Outputs\Clockwork::class
+ *
+ * Debugbar: (make sure you have the barryvdh/laravel-debugbar package installed)
+ * Writes the N+1 queries into a custom messages collector of Debugbar
+ * \BeyondCode\QueryDetector\Outputs\Debugbar::class
+ *
+ * JSON:
+ * Writes the N+1 queries into the response body of your JSON responses
+ * \BeyondCode\QueryDetector\Outputs\Json::class
+ *
+ * Log:
+ * Writes the N+1 queries into the Laravel.log file
+ * \BeyondCode\QueryDetector\Outputs\Log::class
+ */
+ 'output' => [
+ \BeyondCode\QueryDetector\Outputs\Alert::class,
+ \BeyondCode\QueryDetector\Outputs\Log::class,
+ ]
+];
diff --git a/vendor/beyondcode/laravel-query-detector/docs/_index.md b/vendor/beyondcode/laravel-query-detector/docs/_index.md
new file mode 100644
index 000000000..ed8a55ef4
--- /dev/null
+++ b/vendor/beyondcode/laravel-query-detector/docs/_index.md
@@ -0,0 +1,4 @@
+---
+packageName: Laravel Query Detector
+githubUrl: https://github.com/beyondcode/laravel-query-detector
+---
\ No newline at end of file
diff --git a/vendor/beyondcode/laravel-query-detector/docs/installation.md b/vendor/beyondcode/laravel-query-detector/docs/installation.md
new file mode 100644
index 000000000..3559ca203
--- /dev/null
+++ b/vendor/beyondcode/laravel-query-detector/docs/installation.md
@@ -0,0 +1,17 @@
+---
+title: Installation
+order: 1
+---
+# Laravel N+1 Query Detector
+
+The Laravel N+1 query detector helps you to increase your application's performance by reducing the number of queries it executes. This package monitors your queries in real-time, while you develop your application and notify you when you should add eager loading (N+1 queries).
+
+# Installation
+
+You can install the package via composer:
+
+```
+composer require beyondcode/laravel-query-detector --dev
+```
+
+The package will automatically register itself.
\ No newline at end of file
diff --git a/vendor/beyondcode/laravel-query-detector/docs/usage.md b/vendor/beyondcode/laravel-query-detector/docs/usage.md
new file mode 100644
index 000000000..be34cfdbf
--- /dev/null
+++ b/vendor/beyondcode/laravel-query-detector/docs/usage.md
@@ -0,0 +1,92 @@
+---
+title: Usage
+order: 2
+---
+
+## Usage
+
+If you run your application in the `debug` mode, the query monitor will be automatically active. So there is nothing you have to do.
+
+By default, this package will display an `alert()` message to notify you about an N+1 query found in the current request.
+
+If you rather want this information to be written to your `laravel.log` file, written to your browser's console log as a warning or listed in a new tab for the [Laravel Debugbar (barryvdh/laravel-debugbar)](https://github.com/barryvdh/laravel-debugbar), you can publish the configuration and change the output behaviour (see example below).
+
+You can publish the package's configuration using this command:
+
+```bash
+php artisan vendor:publish --provider="BeyondCode\QueryDetector\QueryDetectorServiceProvider"
+```
+
+This will add the `querydetector.php` file in your config directory with the following contents:
+
+```php
+return [
+ /*
+ * Enable or disable the query detection.
+ * If this is set to "null", the app.debug config value will be used.
+ */
+ 'enabled' => env('QUERY_DETECTOR_ENABLED', null),
+
+ /*
+ * Threshold level for the N+1 query detection. If a relation query will be
+ * executed more then this amount, the detector will notify you about it.
+ */
+ 'threshold' => (int) env('QUERY_DETECTOR_THRESHOLD', 1),
+
+ /*
+ * Here you can whitelist model relations.
+ *
+ * Right now, you need to define the model relation both as the class name and the attribute name on the model.
+ * So if an "Author" model would have a "posts" relation that points to a "Post" class, you need to add both
+ * the "posts" attribute and the "Post::class", since the relation can get resolved in multiple ways.
+ */
+ 'except' => [
+ //Author::class => [
+ // Post::class,
+ // 'posts',
+ //]
+ ],
+
+ /*
+ * Define the output format that you want to use. Multiple classes are supported.
+ * Available options are:
+ *
+ * Alert:
+ * Displays an alert on the website
+ * \BeyondCode\QueryDetector\Outputs\Alert::class
+ *
+ * Console:
+ * Writes the N+1 queries into your browsers console log
+ * \BeyondCode\QueryDetector\Outputs\Console::class
+ *
+ * Clockwork: (make sure you have the itsgoingd/clockwork package installed)
+ * Writes the N+1 queries warnings to Clockwork log
+ * \BeyondCode\QueryDetector\Outputs\Clockwork::class
+ *
+ * Debugbar: (make sure you have the barryvdh/laravel-debugbar package installed)
+ * Writes the N+1 queries into a custom messages collector of Debugbar
+ * \BeyondCode\QueryDetector\Outputs\Debugbar::class
+ *
+ * JSON:
+ * Writes the N+1 queries into the response body of your JSON responses
+ * \BeyondCode\QueryDetector\Outputs\Json::class
+ *
+ * Log:
+ * Writes the N+1 queries into the Laravel.log file
+ * \BeyondCode\QueryDetector\Outputs\Log::class
+ */
+ 'output' => [
+ \BeyondCode\QueryDetector\Outputs\Log::class,
+ \BeyondCode\QueryDetector\Outputs\Alert::class,
+ ]
+
+];
+```
+
+If you use **Lumen**, you need to copy the config file manually and register the Lumen Service Provider in `bootstrap/app.php` file
+
+```php
+$app->register(\BeyondCode\QueryDetector\LumenQueryDetectorServiceProvider::class);
+```
+
+If you need additional logic to run when the package detects unoptimized queries, you can listen to the `\BeyondCode\QueryDetector\Events\QueryDetected` event and write a listener to run your own handler. (e.g. send warning to Sentry/Bugsnag, send Slack notification, etc.)
diff --git a/vendor/beyondcode/laravel-query-detector/src/Events/QueryDetected.php b/vendor/beyondcode/laravel-query-detector/src/Events/QueryDetected.php
new file mode 100644
index 000000000..635ac4f88
--- /dev/null
+++ b/vendor/beyondcode/laravel-query-detector/src/Events/QueryDetected.php
@@ -0,0 +1,26 @@
+queries = $queries;
+ }
+
+ /**
+ * @return Collection
+ */
+ public function getQueries()
+ {
+ return $this->queries;
+ }
+}
diff --git a/vendor/beyondcode/laravel-query-detector/src/LumenQueryDetectorServiceProvider.php b/vendor/beyondcode/laravel-query-detector/src/LumenQueryDetectorServiceProvider.php
new file mode 100644
index 000000000..c73202ec4
--- /dev/null
+++ b/vendor/beyondcode/laravel-query-detector/src/LumenQueryDetectorServiceProvider.php
@@ -0,0 +1,21 @@
+app->configure('querydetector');
+ $this->mergeConfigFrom(__DIR__ . '/../config/config.php', 'querydetector');
+
+ $this->app->middleware([
+ QueryDetectorMiddleware::class
+ ]);
+
+ $this->app->singleton(QueryDetector::class);
+ $this->app->alias(QueryDetector::class, 'querydetector');
+ }
+}
diff --git a/vendor/beyondcode/laravel-query-detector/src/Outputs/Alert.php b/vendor/beyondcode/laravel-query-detector/src/Outputs/Alert.php
new file mode 100644
index 000000000..08eb3c766
--- /dev/null
+++ b/vendor/beyondcode/laravel-query-detector/src/Outputs/Alert.php
@@ -0,0 +1,53 @@
+headers->get('Content-Type'), 'text/html') !== 0 || $response->isRedirection()) {
+ return;
+ }
+
+ $content = $response->getContent();
+
+ $outputContent = $this->getOutputContent($detectedQueries);
+
+ $pos = strripos($content, '