diff --git a/public/app.js b/public/app.js index 021463ef3..523b48b0f 100644 --- a/public/app.js +++ b/public/app.js @@ -50567,7 +50567,25 @@ var render = function() { ] ) ]) - ]) + ]), + _vm._v(" "), + slotProps.entry.content.file + ? _c("tr", [ + _c("td", { staticClass: "table-fit font-weight-bold" }, [ + _vm._v("Location") + ]), + _vm._v(" "), + _c("td", [ + _vm._v( + "\n " + + _vm._s(slotProps.entry.content.file) + + ":" + + _vm._s(slotProps.entry.content.line) + + "\n " + ) + ]) + ]) + : _vm._e() ] } }, diff --git a/public/mix-manifest.json b/public/mix-manifest.json index c524af240..8325f0a84 100644 --- a/public/mix-manifest.json +++ b/public/mix-manifest.json @@ -1,5 +1,5 @@ { - "/app.js": "/app.js?id=8b839cf52d8d2895ec73", + "/app.js": "/app.js?id=cfc93f63ab192bcfa68d", "/app.css": "/app.css?id=7c1ff2a14db6cf79b2c3", "/app-dark.css": "/app-dark.css?id=3499432c9dbc93b0f541" } \ No newline at end of file diff --git a/resources/js/screens/gates/preview.vue b/resources/js/screens/gates/preview.vue index 74d34c786..a84f37339 100644 --- a/resources/js/screens/gates/preview.vue +++ b/resources/js/screens/gates/preview.vue @@ -34,6 +34,13 @@ + + + Location + + {{slotProps.entry.content.file}}:{{slotProps.entry.content.line}} + +
diff --git a/src/Watchers/FetchesStackTrace.php b/src/Watchers/FetchesStackTrace.php new file mode 100644 index 000000000..8c8caf504 --- /dev/null +++ b/src/Watchers/FetchesStackTrace.php @@ -0,0 +1,40 @@ +forget(0); + + return $trace->first(function ($frame) { + if (! isset($frame['file'])) { + return false; + } + + return ! Str::contains($frame['file'], + base_path('vendor'.DIRECTORY_SEPARATOR.$this->ignoredVendorPath()) + ); + }); + } + + /** + * Choose the frame outside of either Telescope/Laravel or all packages. + * + * @return string|null + */ + protected function ignoredVendorPath() + { + if (! ($this->options['ignore_packages'] ?? true)) { + return 'laravel'; + } + } +} diff --git a/src/Watchers/GateWatcher.php b/src/Watchers/GateWatcher.php index b5bdea189..af16268db 100644 --- a/src/Watchers/GateWatcher.php +++ b/src/Watchers/GateWatcher.php @@ -10,6 +10,8 @@ class GateWatcher extends Watcher { + use FetchesStackTrace; + /** * Register the watcher. * @@ -36,10 +38,14 @@ public function recordGateCheck(?Authenticatable $user, $ability, $result, $argu return; } + $caller = $this->getCallerFromStackTrace(); + Telescope::recordGate(IncomingEntry::make([ 'ability' => $ability, 'result' => $result ? 'allowed' : 'denied', 'arguments' => $arguments, + 'file' => $caller['file'], + 'line' => $caller['line'], ])); return $result; diff --git a/src/Watchers/QueryWatcher.php b/src/Watchers/QueryWatcher.php index 6e6252712..759d91cb0 100644 --- a/src/Watchers/QueryWatcher.php +++ b/src/Watchers/QueryWatcher.php @@ -2,13 +2,14 @@ namespace Laravel\Telescope\Watchers; -use Illuminate\Support\Str; use Laravel\Telescope\Telescope; use Laravel\Telescope\IncomingEntry; use Illuminate\Database\Events\QueryExecuted; class QueryWatcher extends Watcher { + use FetchesStackTrace; + /** * Register the watcher. * @@ -68,36 +69,4 @@ protected function formatBindings($event) { return $event->connection->prepareBindings($event->bindings); } - - /** - * Find the first frame in the stack trace outside of Telescope/Laravel. - * - * @return array - */ - protected function getCallerFromStackTrace() - { - $trace = collect(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS))->forget(0); - - return $trace->first(function ($frame) { - if (! isset($frame['file'])) { - return false; - } - - return ! Str::contains($frame['file'], - base_path('vendor'.DIRECTORY_SEPARATOR.$this->ignoredVendorPath()) - ); - }); - } - - /** - * Choose the frame outside of either Telescope/Laravel or all packages. - * - * @return string|null - */ - protected function ignoredVendorPath() - { - if (! ($this->options['ignore_packages'] ?? true)) { - return 'laravel'; - } - } }