mirror of
https://github.com/HDInnovations/UNIT3D-Community-Edition.git
synced 2026-02-09 13:14:07 -06:00
Just an initial portion for now fixing incorrect text and preventing future incorrect text. Eventually, I'd like to fix everything still listed under "ignoredWords" in cspell.json.
146 lines
4.6 KiB
PHP
146 lines
4.6 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
/**
|
|
* NOTICE OF LICENSE.
|
|
*
|
|
* UNIT3D Community Edition is open-sourced software licensed under the GNU Affero General Public License v3.0
|
|
* The details is bundled with this project in the file LICENSE.txt.
|
|
*
|
|
* @project UNIT3D Community Edition
|
|
*
|
|
* @author HDVinnie <hdinnovations@protonmail.com>
|
|
* @license https://www.gnu.org/licenses/agpl-3.0.en.html/ GNU Affero General Public License v3.0
|
|
*/
|
|
|
|
namespace App\Http\Livewire;
|
|
|
|
use App\Traits\CastLivewireProperties;
|
|
use Illuminate\Pagination\LengthAwarePaginator;
|
|
use Illuminate\Support\Facades\File;
|
|
use Livewire\Attributes\Computed;
|
|
use Livewire\Attributes\Url;
|
|
use Livewire\Component;
|
|
use Livewire\WithPagination;
|
|
use SplFileInfo;
|
|
|
|
/**
|
|
* @property \Illuminate\Support\Collection $logFiles
|
|
* @property LengthAwarePaginator $entries
|
|
*/
|
|
class LaravelLogViewer extends Component
|
|
{
|
|
use CastLivewireProperties;
|
|
use WithPagination;
|
|
|
|
/**
|
|
* @var int[]|string[]
|
|
*/
|
|
public array $logs = [0];
|
|
|
|
public int $page = 1;
|
|
|
|
#[Url(history: true)]
|
|
public int $perPage = 5;
|
|
|
|
final public function updating(string $field, mixed &$value): void
|
|
{
|
|
$this->castLivewireProperties($field, $value);
|
|
}
|
|
|
|
final public function loadMore(): void
|
|
{
|
|
$this->perPage += 5;
|
|
}
|
|
|
|
#[Computed]
|
|
final public function logFiles()
|
|
{
|
|
$directory = storage_path('logs');
|
|
|
|
return collect(File::allFiles($directory))
|
|
->sortByDesc(fn (SplFileInfo $file) => $file->getMTime())->values();
|
|
}
|
|
|
|
/**
|
|
* @return LengthAwarePaginator<\Illuminate\Support\Collection<string|int, mixed>>
|
|
*/
|
|
#[Computed]
|
|
final public function entries(): LengthAwarePaginator
|
|
{
|
|
$files = $this->logFiles;
|
|
$logString = '';
|
|
|
|
foreach ($this->logs as $log) {
|
|
if ($files[$log] ?? []) {
|
|
$logString .= file_get_contents($files[$log]->getPathname());
|
|
}
|
|
}
|
|
|
|
$entryPattern = '/^\[(?<date>.*)\]\s(?<env>\w+)\.(?<level>\w+)\:\s/m';
|
|
$contextPattern = '/^(?<message>[^\{]*)?(?:\{"exception"\:"\[object\]\s\((?<exception>[^\s\(]+))?.*\s(?:in|at)\s(?<in>.*)\:(?<line>\d+)\)?/ms';
|
|
|
|
$entries = collect();
|
|
|
|
if (preg_match_all($entryPattern, $logString, $entryMatches, PREG_SET_ORDER) !== false) {
|
|
$stacktraces = preg_split($entryPattern, $logString);
|
|
// Delete the empty first entry
|
|
array_shift($stacktraces);
|
|
$numEntries = \count($entryMatches);
|
|
|
|
for ($i = 0; $i < $numEntries; $i++) {
|
|
// The context is the portion before the first stack trace
|
|
$context = preg_split('/^\[stacktrace\]|Stack trace\:/ms', (string) $stacktraces[$i])[0];
|
|
// The `context` consists of a message, an exception, a filename, and a line count
|
|
preg_match($contextPattern, $context, $contextMatches);
|
|
|
|
$entries->push([
|
|
'date' => $entryMatches[$i]['date'],
|
|
'env' => $entryMatches[$i]['env'],
|
|
'level' => $entryMatches[$i]['level'],
|
|
'message' => $contextMatches['message'] ?? '',
|
|
'exception' => $contextMatches['exception'] ?? '',
|
|
'in' => $contextMatches['in'] ?? '',
|
|
'line' => $contextMatches['line'] ?? '',
|
|
'stacktrace' => $stacktraces[$i],
|
|
]);
|
|
}
|
|
}
|
|
|
|
$groupedEntries = $entries->groupBy(fn ($entry) => $entry['message'].'-'.$entry['exception'].'-'.$entry['in'].'-'.$entry['line']);
|
|
$currentEntries = $groupedEntries->forPage($this->page, $this->perPage);
|
|
|
|
return new LengthAwarePaginator($currentEntries, $groupedEntries->count(), $this->perPage, $this->page);
|
|
}
|
|
|
|
final public function clearLatestLog(): void
|
|
{
|
|
$latestLogFile = $this->logFiles->first();
|
|
|
|
if ($latestLogFile) {
|
|
File::put($latestLogFile->getPathname(), '');
|
|
}
|
|
}
|
|
|
|
final public function deleteAllLogs(): void
|
|
{
|
|
$directory = storage_path('logs');
|
|
$files = File::allFiles($directory);
|
|
|
|
foreach ($files as $file) {
|
|
File::delete($file->getPathname());
|
|
}
|
|
}
|
|
|
|
final public function render(): \Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View|\Illuminate\Contracts\Foundation\Application
|
|
{
|
|
return view('livewire.laravel-log-viewer', [
|
|
'files' => $this->logFiles,
|
|
'entries' => $this->entries,
|
|
])
|
|
->extends('layout.default')
|
|
->section('content');
|
|
}
|
|
}
|