1a3092f6cSAndreas Gohr<?php 2a3092f6cSAndreas Gohr 3a3092f6cSAndreas Gohruse dokuwiki\plugin\cachestats\FileStatistics; 4a3092f6cSAndreas Gohruse splitbrain\phpcli\Options; 5a3092f6cSAndreas Gohruse splitbrain\phpcli\TableFormatter; 6a3092f6cSAndreas Gohr 7a3092f6cSAndreas Gohr/** 8a3092f6cSAndreas Gohr * DokuWiki Plugin cachestats (CLI Component) 9a3092f6cSAndreas Gohr * 10a3092f6cSAndreas Gohr * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 11a3092f6cSAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 12a3092f6cSAndreas Gohr */ 13a3092f6cSAndreas Gohrclass cli_plugin_cachestats extends \dokuwiki\Extension\CLIPlugin 14a3092f6cSAndreas Gohr{ 15a3092f6cSAndreas Gohr /** @inheritDoc */ 16a3092f6cSAndreas Gohr protected function setup(Options $options) 17a3092f6cSAndreas Gohr { 18a3092f6cSAndreas Gohr $options->setHelp('Collect statistics about the cache directory.'); 19a3092f6cSAndreas Gohr 20*a6282b43SAndreas Gohr $options->registerOption('noprogress', 'Don\'t show progress dots'); 21*a6282b43SAndreas Gohr $options->registerOption('format', 'Output format. Defaults to table.', 'f', 'table|json|csv'); 22*a6282b43SAndreas Gohr $options->registerOption('sort', 'Sort by this criteria. Defaults to size.', 's', 'count|size|dups'); 23a3092f6cSAndreas Gohr } 24a3092f6cSAndreas Gohr 25a3092f6cSAndreas Gohr /** @inheritDoc */ 26a3092f6cSAndreas Gohr protected function main(Options $options) 27a3092f6cSAndreas Gohr { 28a3092f6cSAndreas Gohr global $conf; 29a3092f6cSAndreas Gohr 30a3092f6cSAndreas Gohr $sort = $options->getOpt('sort', 'size'); 31a3092f6cSAndreas Gohr if (!in_array($sort, ['count', 'size', 'dups'])) { 32a3092f6cSAndreas Gohr $this->error("Invalid sort option '$sort'. Allowed are: count, size, dups."); 33a3092f6cSAndreas Gohr return 1; 34a3092f6cSAndreas Gohr } 35a3092f6cSAndreas Gohr 369cff4bafSAndreas Gohr $format = $options->getOpt('format', 'table'); 379cff4bafSAndreas Gohr if (!in_array($format, ['table', 'json', 'csv'])) { 389cff4bafSAndreas Gohr $this->error("Invalid format option '$format'. Allowed are: table, json, csv."); 399cff4bafSAndreas Gohr return 1; 409cff4bafSAndreas Gohr } 419cff4bafSAndreas Gohr 42*a6282b43SAndreas Gohr // progress report - collecting stats can take a while 43a3092f6cSAndreas Gohr fprintf(STDERR, 'Collecting cache statistics from ' . $conf['cachedir'] . "…\n"); 44*a6282b43SAndreas Gohr if(!$options->getOpt('noprogress')) { 45*a6282b43SAndreas Gohr $cb = function($count) { 46*a6282b43SAndreas Gohr if ($count % 50000 === 0) { 47*a6282b43SAndreas Gohr fprintf(STDERR, "%s files processed\n", number_format($count)); 48*a6282b43SAndreas Gohr } elseif ($count % 1000 === 0) { 49*a6282b43SAndreas Gohr fprintf(STDERR, "."); 50*a6282b43SAndreas Gohr } 51*a6282b43SAndreas Gohr }; 52a3092f6cSAndreas Gohr } else { 53*a6282b43SAndreas Gohr $cb = null; 54a3092f6cSAndreas Gohr } 55a3092f6cSAndreas Gohr 56*a6282b43SAndreas Gohr $result = (new FileStatistics($conf['cachedir']))->collect($cb); 57*a6282b43SAndreas Gohr if($cb) fprintf(STDERR, "\n"); 58a3092f6cSAndreas Gohr 59a3092f6cSAndreas Gohr // sort with preserved keys 60a3092f6cSAndreas Gohr uasort($result, function ($a, $b) use ($sort) { 61a3092f6cSAndreas Gohr return $b[$sort] <=> $a[$sort]; 62a3092f6cSAndreas Gohr }); 63a3092f6cSAndreas Gohr 649cff4bafSAndreas Gohr match ($format) { 659cff4bafSAndreas Gohr 'json' => $this->print_json($result), 669cff4bafSAndreas Gohr 'csv' => $this->print_csv($result), 679cff4bafSAndreas Gohr default => $this->print_table($result), 689cff4bafSAndreas Gohr }; 69a3092f6cSAndreas Gohr return 0; 70a3092f6cSAndreas Gohr } 71a3092f6cSAndreas Gohr 729cff4bafSAndreas Gohr /** 739cff4bafSAndreas Gohr * Output statistics as JSON 749cff4bafSAndreas Gohr */ 759cff4bafSAndreas Gohr private function print_json(array $result): void 769cff4bafSAndreas Gohr { 779cff4bafSAndreas Gohr echo json_encode($result, JSON_PRETTY_PRINT); 789cff4bafSAndreas Gohr } 799cff4bafSAndreas Gohr 809cff4bafSAndreas Gohr /** 819cff4bafSAndreas Gohr * Output statistics as CSV 829cff4bafSAndreas Gohr */ 839cff4bafSAndreas Gohr private function print_csv(array $result): void 849cff4bafSAndreas Gohr { 859cff4bafSAndreas Gohr $handle = fopen('php://output', 'w'); 869cff4bafSAndreas Gohr if ($handle === false) { 879cff4bafSAndreas Gohr $this->error('Could not open output for CSV.'); 889cff4bafSAndreas Gohr return; 899cff4bafSAndreas Gohr } 909cff4bafSAndreas Gohr 91bd0f08c8SAndreas Gohr $header = array_merge(['extension'], array_keys(reset($result))); 929cff4bafSAndreas Gohr fputcsv($handle, $header); 939cff4bafSAndreas Gohr 949cff4bafSAndreas Gohr foreach ($result as $ext => $data) { 95bd0f08c8SAndreas Gohr fputcsv($handle, array_merge([$ext], $data)); 969cff4bafSAndreas Gohr } 979cff4bafSAndreas Gohr } 989cff4bafSAndreas Gohr 999cff4bafSAndreas Gohr /** 1009cff4bafSAndreas Gohr * Output statistics as table 1019cff4bafSAndreas Gohr */ 1029cff4bafSAndreas Gohr private function print_table(array $result): void 1039cff4bafSAndreas Gohr { 104bd0f08c8SAndreas Gohr $colWidth = 9; 105bd0f08c8SAndreas Gohr 106bd0f08c8SAndreas Gohr $headers = array_merge(['ext'], array_keys(reset($result))); 107bd0f08c8SAndreas Gohr $widths = array_merge(['*'], array_fill(0, count($headers) -1, $colWidth)); 108bd0f08c8SAndreas Gohr $colors = array_fill(0, count($headers), ''); 109bd0f08c8SAndreas Gohr 110bd0f08c8SAndreas Gohr // ensure terminal is wide enough, otherwise break ugly 111a3092f6cSAndreas Gohr $tr = new TableFormatter($this->colors); 112bd0f08c8SAndreas Gohr if($tr->getMaxWidth() < $colWidth * count($headers)){; 113bd0f08c8SAndreas Gohr $tr->setMaxWidth($colWidth * count($headers) + 10); 114bd0f08c8SAndreas Gohr } 115bd0f08c8SAndreas Gohr 116bd0f08c8SAndreas Gohr echo $tr->format($widths, $headers, $colors); 117a3092f6cSAndreas Gohr 118a3092f6cSAndreas Gohr foreach ($result as $ext => $data) { 119bd0f08c8SAndreas Gohr array_walk( 120bd0f08c8SAndreas Gohr $data, 121bd0f08c8SAndreas Gohr fn (&$v, $k) => $v = sprintf( 122bd0f08c8SAndreas Gohr "% ${colWidth}s", 123bd0f08c8SAndreas Gohr ($k == 'size') ? filesize_h($v) : number_format($v) 124bd0f08c8SAndreas Gohr ) 125bd0f08c8SAndreas Gohr ); 126bd0f08c8SAndreas Gohr 1279cff4bafSAndreas Gohr echo $tr->format( 128bd0f08c8SAndreas Gohr $widths, 129bd0f08c8SAndreas Gohr array_merge([$ext], array_values($data)), 130bd0f08c8SAndreas Gohr $colors 131a3092f6cSAndreas Gohr ); 132a3092f6cSAndreas Gohr } 133a3092f6cSAndreas Gohr } 134a3092f6cSAndreas Gohr} 135