diff --git a/.travis.yml b/.travis.yml index 4b0fcb4..d772ef9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,7 +10,7 @@ install: - travis_retry composer install --no-interaction --prefer-source script: - - vendor/bin/phpunit + - XDEBUG_MODE=coverage vendor/bin/phpunit after_script: - wget https://scrutinizer-ci.com/ocular.phar diff --git a/README.md b/README.md index 1b9888e..54689ac 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,10 @@ Rap2hpoutre\LaravelLogViewer\LaravelLogViewerServiceProvider::class, Add a route in your web routes file: ```php Route::get('logs', '\Rap2hpoutre\LaravelLogViewer\LogViewerController@index'); + +or +// Laravel 8+ +Route::get('logs', [\Rap2hpoutre\LaravelLogViewer\LogViewerController::class, 'index']); ``` Go to `http://myapp/logs` or some other route diff --git a/src/Rap2hpoutre/LaravelLogViewer/LaravelLogViewer.php b/src/Rap2hpoutre/LaravelLogViewer/LaravelLogViewer.php index 3077f87..8b31ca0 100644 --- a/src/Rap2hpoutre/LaravelLogViewer/LaravelLogViewer.php +++ b/src/Rap2hpoutre/LaravelLogViewer/LaravelLogViewer.php @@ -55,23 +55,27 @@ public function __construct() public function setFolder($folder) { if (app('files')->exists($folder)) { + $this->folder = $folder; } - if(is_array($this->storage_path)) { + else if(is_array($this->storage_path)) { + foreach ($this->storage_path as $value) { + $logsPath = $value . '/' . $folder; + if (app('files')->exists($logsPath)) { $this->folder = $folder; break; } } } else { - if ($this->storage_path) { + $logsPath = $this->storage_path . '/' . $folder; if (app('files')->exists($logsPath)) { $this->folder = $folder; } - } + } } @@ -97,9 +101,11 @@ public function pathToLogFile($file) { if (app('files')->exists($file)) { // try the absolute path + return $file; } if (is_array($this->storage_path)) { + foreach ($this->storage_path as $folder) { if (app('files')->exists($folder . '/' . $file)) { // try the absolute path $file = $folder . '/' . $file; @@ -114,8 +120,9 @@ public function pathToLogFile($file) $file = $logsPath . '/' . $file; // check if requested file is really in the logs directory if (dirname($file) !== $logsPath) { - throw new \Exception('No such log file'); + throw new \Exception('No such log file: '.$file); } + return $file; } @@ -228,29 +235,51 @@ public function all() return array_reverse($log); } - /** - * @return array - */ - public function getFolders() + /**Creates a multidimensional array + * of subdirectories and files + * + * @param null $path + * + * @return array + */ + public function foldersAndFiles($path = null) { - $folders = glob($this->storage_path . '/*', GLOB_ONLYDIR); - if (is_array($this->storage_path)) { - foreach ($this->storage_path as $value) { - $folders = array_merge( - $folders, - glob($value . '/*', GLOB_ONLYDIR) - ); - } - } + $contents = array(); + $dir = $path ? $path : $this->storage_path; + foreach (scandir($dir) as $node) { + if ($node == '.' || $node == '..') continue; + $path = $dir . '\\' . $node; + if (is_dir($path)) { + $contents[$path] = $this->foldersAndFiles($path); + } else { + $contents[] = $path; + } + } + + return $contents; + } - if (is_array($folders)) { - foreach ($folders as $k => $folder) { - $folders[$k] = basename($folder); - } - } - return array_values($folders); + /**Returns an array of + * all subdirectories of specified directory + * + * @param string $folder + * + * @return array + */ + public function getFolders($folder = '') + { + $folders = []; + $listObject = new \RecursiveIteratorIterator( + new \RecursiveDirectoryIterator($this->storage_path.'/'.$folder, \RecursiveDirectoryIterator::SKIP_DOTS), + \RecursiveIteratorIterator::CHILD_FIRST + ); + foreach ($listObject as $fileinfo) { + if($fileinfo->isDir()) $folders[] = $fileinfo->getRealPath(); + } + return $folders; } + /** * @param bool $basename * @return array @@ -267,30 +296,81 @@ public function getFolderFiles($basename = false) */ public function getFiles($basename = false, $folder = '') { - $pattern = function_exists('config') ? config('logviewer.pattern', '*.log') : '*.log'; - $files = glob( - $this->storage_path . '/' . $folder . '/' . $pattern, - preg_match($this->pattern->getPattern('files'), $pattern) ? GLOB_BRACE : 0 - ); - if (is_array($this->storage_path)) { - foreach ($this->storage_path as $value) { - $files = array_merge( - $files, - glob( - $value . '/' . $folder . '/' . $pattern, - preg_match($this->pattern->getPattern('files'), $pattern) ? GLOB_BRACE : 0 - ) - ); - } - } + $files = []; + $pattern = function_exists('config') ? config('logviewer.pattern', '*.log') : '*.log'; + $fullPath = $this->storage_path.'/'.$folder; - $files = array_reverse($files); - $files = array_filter($files, 'is_file'); - if ($basename && is_array($files)) { - foreach ($files as $k => $file) { - $files[$k] = basename($file); - } - } - return array_values($files); + $listObject = new \RecursiveIteratorIterator( + new \RecursiveDirectoryIterator($fullPath, \RecursiveDirectoryIterator::SKIP_DOTS), + \RecursiveIteratorIterator::CHILD_FIRST + ); + + foreach ($listObject as $fileinfo) { + if(!$fileinfo->isDir() && strtolower(pathinfo($fileinfo->getRealPath(), PATHINFO_EXTENSION)) == explode('.', $pattern)[1]) + $files[] = $basename ? basename($fileinfo->getRealPath()) : $fileinfo->getRealPath(); + } + return $files; + + } + + /** + * @return string + */ + public function getStoragePath() + { + return $this->storage_path; } + + /** + * @param $path + * + * @return void + */ + public function setStoragePath($path) + { + $this->storage_path = $path; + } + + public static function directoryTreeStructure($storage_path, array $array) + { + foreach ($array as $k => $v) { + if(is_dir( $k )) { + + $exploded = explode( "\\", $k ); + $show = last( $exploded ); + + echo '
+ +        '.$show.' + +
'; + + if ( is_array( $v ) ) { + self::directoryTreeStructure( $storage_path, $v ); + } + + } + else { + + $exploded = explode( "\\", $v ); + $show2 = last( $exploded ); + $folder = str_replace( $storage_path, "", rtrim( str_replace( $show2, "", $v ), "\\" ) ); + $file = $v; + + + echo '
+ +        '.$show2.' + +
'; + + } + } + + return; + } + + } diff --git a/src/controllers/LogViewerController.php b/src/controllers/LogViewerController.php index aa39ad2..03b7d4d 100644 --- a/src/controllers/LogViewerController.php +++ b/src/controllers/LogViewerController.php @@ -67,6 +67,9 @@ public function index() 'files' => $this->log_viewer->getFiles(true), 'current_file' => $this->log_viewer->getFileName(), 'standardFormat' => true, + 'structure' => $this->log_viewer->foldersAndFiles(), + 'storage_path' => $this->log_viewer->getStoragePath(), + ]; if ($this->request->wantsJson()) { diff --git a/src/views/log.blade.php b/src/views/log.blade.php index aad56db..92ede04 100644 --- a/src/views/log.blade.php +++ b/src/views/log.blade.php @@ -66,6 +66,10 @@ .nowrap { white-space: nowrap; } + .list-group { + padding: 5px; + } + @@ -180,19 +184,10 @@ function resetTheme() {
@foreach($folders as $folder)
- - {{$folder}} - - @if ($current_folder == $folder) -
- @foreach($folder_files as $file) - - {{$file}} - - @endforeach -
- @endif + +
@endforeach @foreach($files as $file) diff --git a/tests/LaravelLogViewerTest.php b/tests/LaravelLogViewerTest.php index 08bb927..f97ae69 100644 --- a/tests/LaravelLogViewerTest.php +++ b/tests/LaravelLogViewerTest.php @@ -3,6 +3,7 @@ namespace Rap2hpoutre\LaravelLogViewer; use Orchestra\Testbench\TestCase as OrchestraTestCase; +use File; /** * Class LaravelLogViewerTest @@ -14,9 +15,10 @@ class LaravelLogViewerTest extends OrchestraTestCase public function setUp() { parent::setUp(); + config()->set('app.key', 'XP0aw2Dkrk22p0JoAOzulOl8XkUxlvkO'); // Copy "laravel.log" file to the orchestra package. - if (!file_exists(storage_path() . '/logs/laravel.log')) { - copy(__DIR__ . '/laravel.log', storage_path() . '/logs/laravel.log'); + if (!file_exists(storage_path('logs/laravel.log'))) { + copy(__DIR__ . '/laravel.log', storage_path('logs/laravel.log')); } } @@ -25,21 +27,92 @@ public function setUp() */ public function testSetFile() { - parent::setUp(); $laravel_log_viewer = new LaravelLogViewer(); - try { - $laravel_log_viewer->setFile("laravel.log"); - } catch (\Exception $e) { - throw new \Exception($e->getMessage()); - } + $laravel_log_viewer->setFile("laravel.log"); $this->assertEquals("laravel.log", $laravel_log_viewer->getFileName()); } + + public function testSetFolderWithCorrectPath() + { + + $laravel_log_viewer = new LaravelLogViewer(); + $laravel_log_viewer->setFolder(basename((__DIR__))); + $this->assertEquals("tests", $laravel_log_viewer->getFolderName()); + } + + + public function testSetFolderWithArrayStoragePath() + { + $path = __DIR__; + + $laravel_log_viewer = new LaravelLogViewer(); + $laravel_log_viewer->setStoragePath([$path]); + if(!\File::exists("$path/samuel")) \File::makeDirectory("$path/samuel"); + $laravel_log_viewer->setFolder('samuel'); + + $this->assertEquals("samuel", $laravel_log_viewer->getFolderName()); + + } + + public function testSetFolderWithDefaultStoragePath() + { + + $laravel_log_viewer = new LaravelLogViewer(); + $laravel_log_viewer->setStoragePath(storage_path()); + $laravel_log_viewer->setFolder('logs'); + + + $this->assertEquals("logs", $laravel_log_viewer->getFolderName()); + + } + + public function testSetStoragePath() + { + + $laravel_log_viewer = new LaravelLogViewer(); + $laravel_log_viewer->setStoragePath(basename(__DIR__)); + + $this->assertEquals("tests", $laravel_log_viewer->getStoragePath()); + } + + public function testPathToLogFile() + { + + $laravel_log_viewer = new LaravelLogViewer(); + $pathToLogFile = $laravel_log_viewer->pathToLogFile(storage_path(('logs/laravel.log'))); + + $this->assertEquals($pathToLogFile, storage_path('logs/laravel.log')); + } + + public function testPathToLogFileWithArrayStoragePath() + { + + $laravel_log_viewer = new LaravelLogViewer(); + $laravel_log_viewer->setStoragePath([storage_path()]); + $pathToLogFile = $laravel_log_viewer->pathToLogFile('laravel.log'); + + $this->assertEquals($pathToLogFile, 'laravel.log'); + } + + public function testFailOnBadPathToLogFile() + { + + $this->expectException(\Exception::class); + + $laravel_log_viewer = new LaravelLogViewer(); + $laravel_log_viewer->setStoragePath(storage_path()); + $laravel_log_viewer->setFolder('logs'); + $laravel_log_viewer->pathToLogFile('newlogs/nolaravel.txt'); + } + public function testAll() { $laravel_log_viewer = new LaravelLogViewer(); + $laravel_log_viewer->setStoragePath(__DIR__); + $laravel_log_viewer->pathToLogFile(storage_path('logs/laravel.log')); $data = $laravel_log_viewer->all(); $this->assertEquals('local', $data[0]['context']); $this->assertEquals('error', $data[0]['level']); @@ -48,11 +121,72 @@ public function testAll() $this->assertEquals('2018-09-05 20:20:51', $data[0]['date']); } + public function testAllWithEmptyFileName() + { + $laravel_log_viewer = new LaravelLogViewer(); + $laravel_log_viewer->setStoragePath(__DIR__); + + $data = $laravel_log_viewer->all(); + $this->assertEquals('local', $data[0]['context']); + $this->assertEquals('error', $data[0]['level']); + $this->assertEquals('danger', $data[0]['level_class']); + $this->assertEquals('exclamation-triangle', $data[0]['level_img']); + $this->assertEquals('2018-09-05 20:20:51', $data[0]['date']); + } + + public function testFolderFiles() + { + $laravel_log_viewer = new LaravelLogViewer(); + $laravel_log_viewer->setStoragePath(__DIR__); + $data = $laravel_log_viewer->foldersAndFiles(); + $this->assertIsArray($data); + + $this->assertIsArray($data); + $this->assertNotEmpty($data); + + $this->assertStringContainsString('tests', $data[count(explode($data[0], '/')) - 1]); + } + public function testGetFolderFiles() { $laravel_log_viewer = new LaravelLogViewer(); + $laravel_log_viewer->setStoragePath(__DIR__); $data = $laravel_log_viewer->getFolderFiles(); - $this->assertNotEmpty($data[0], "Folder files is null"); + + $this->assertIsArray($data); + $this->assertNotEmpty($data, "Folder files is null"); } + public function testGetFiles() + { + $laravel_log_viewer = new LaravelLogViewer(); + $laravel_log_viewer->setStoragePath(storage_path()); + $data = $laravel_log_viewer->getFiles(); + + $this->assertIsArray($data); + $this->assertNotEmpty($data, "Folder files is null"); + } + + public function testGetFolders() + { + $laravel_log_viewer = new LaravelLogViewer(); + $laravel_log_viewer->setStoragePath(storage_path()); + $data = $laravel_log_viewer->getFolders(); + + $this->assertIsArray($data); + $this->assertNotEmpty($data, "files is null"); + } + + public function testDirectoryStructure() + { + $log_viewer = new LaravelLogViewer(); + ob_start(); + $log_viewer->directoryTreeStructure(storage_path('logs'), $log_viewer->foldersAndFiles()); + $data = ob_get_clean(); + + $this->assertIsString($data); + $this->assertNotEmpty($data); + } + + }