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{ 159cff4bafSAndreas Gohr /** @var string[] */ 169cff4bafSAndreas Gohr private array $buckets = ['<1d', '<1w', '<1m', '<3m', '<6m', '<1y', '>1y']; 179cff4bafSAndreas Gohr 18a3092f6cSAndreas Gohr /** @inheritDoc */ 19a3092f6cSAndreas Gohr protected function setup(Options $options) 20a3092f6cSAndreas Gohr { 21a3092f6cSAndreas Gohr $options->setHelp('Collect statistics about the cache directory.'); 22a3092f6cSAndreas Gohr 239cff4bafSAndreas Gohr $options->registerOption('format', 'Output format: table|json|csv', 'f', 'table'); 24a3092f6cSAndreas Gohr $options->registerOption('sort', 'Sort by count|size|dups', 's', false); 25a3092f6cSAndreas Gohr } 26a3092f6cSAndreas Gohr 27a3092f6cSAndreas Gohr /** @inheritDoc */ 28a3092f6cSAndreas Gohr protected function main(Options $options) 29a3092f6cSAndreas Gohr { 30a3092f6cSAndreas Gohr global $conf; 31a3092f6cSAndreas Gohr 32a3092f6cSAndreas Gohr $sort = $options->getOpt('sort', 'size'); 33a3092f6cSAndreas Gohr if (!in_array($sort, ['count', 'size', 'dups'])) { 34a3092f6cSAndreas Gohr $this->error("Invalid sort option '$sort'. Allowed are: count, size, dups."); 35a3092f6cSAndreas Gohr return 1; 36a3092f6cSAndreas Gohr } 37a3092f6cSAndreas Gohr 389cff4bafSAndreas Gohr $format = $options->getOpt('format', 'table'); 399cff4bafSAndreas Gohr if (!in_array($format, ['table', 'json', 'csv'])) { 409cff4bafSAndreas Gohr $this->error("Invalid format option '$format'. Allowed are: table, json, csv."); 419cff4bafSAndreas Gohr return 1; 429cff4bafSAndreas Gohr } 439cff4bafSAndreas Gohr 449cff4bafSAndreas Gohr if ($format === 'json') { 45a3092f6cSAndreas Gohr fprintf(STDERR, 'Collecting cache statistics from ' . $conf['cachedir'] . "…\n"); 46a3092f6cSAndreas Gohr } else { 47a3092f6cSAndreas Gohr $this->info('Collecting cache statistics from ' . $conf['cachedir'] . '…'); 48a3092f6cSAndreas Gohr } 49a3092f6cSAndreas Gohr 50a3092f6cSAndreas Gohr $stats = (new FileStatistics($conf['cachedir']))->collect(); 51a3092f6cSAndreas Gohr 52a3092f6cSAndreas Gohr // for debugging 53a3092f6cSAndreas Gohr print_r($stats); 54a3092f6cSAndreas Gohr 55a3092f6cSAndreas Gohr $keys = array_unique( 56a3092f6cSAndreas Gohr array_merge( 57a3092f6cSAndreas Gohr array_keys($stats['extensions']), 58a3092f6cSAndreas Gohr array_keys($stats['sizes']), 59a3092f6cSAndreas Gohr array_keys($stats['duplicates']) 60a3092f6cSAndreas Gohr ) 61a3092f6cSAndreas Gohr ); 62a3092f6cSAndreas Gohr $result = []; 63a3092f6cSAndreas Gohr foreach ($keys as $key) { 64a3092f6cSAndreas Gohr $result[$key] = [ 65a3092f6cSAndreas Gohr 'count' => $stats['extensions'][$key] ?? 0, 66a3092f6cSAndreas Gohr 'size' => $stats['sizes'][$key] ?? 0, 67a3092f6cSAndreas Gohr 'dups' => $stats['duplicates'][$key] ?? 0, 68a3092f6cSAndreas Gohr ]; 69*bd0f08c8SAndreas Gohr foreach ($this->buckets as $bucket) { 70*bd0f08c8SAndreas Gohr $result[$key][$bucket] = $stats['modified_groups'][$key][$bucket] ?? 0; 71*bd0f08c8SAndreas Gohr } 72a3092f6cSAndreas Gohr } 73a3092f6cSAndreas Gohr 74a3092f6cSAndreas Gohr // sort with preserved keys 75a3092f6cSAndreas Gohr uasort($result, function ($a, $b) use ($sort) { 76a3092f6cSAndreas Gohr return $b[$sort] <=> $a[$sort]; 77a3092f6cSAndreas Gohr }); 78a3092f6cSAndreas Gohr 799cff4bafSAndreas Gohr match ($format) { 809cff4bafSAndreas Gohr 'json' => $this->print_json($result), 819cff4bafSAndreas Gohr 'csv' => $this->print_csv($result), 829cff4bafSAndreas Gohr default => $this->print_table($result), 839cff4bafSAndreas Gohr }; 84a3092f6cSAndreas Gohr return 0; 85a3092f6cSAndreas Gohr } 86a3092f6cSAndreas Gohr 879cff4bafSAndreas Gohr /** 889cff4bafSAndreas Gohr * Output statistics as JSON 899cff4bafSAndreas Gohr */ 909cff4bafSAndreas Gohr private function print_json(array $result): void 919cff4bafSAndreas Gohr { 929cff4bafSAndreas Gohr echo json_encode($result, JSON_PRETTY_PRINT); 939cff4bafSAndreas Gohr } 949cff4bafSAndreas Gohr 959cff4bafSAndreas Gohr /** 969cff4bafSAndreas Gohr * Output statistics as CSV 979cff4bafSAndreas Gohr */ 989cff4bafSAndreas Gohr private function print_csv(array $result): void 999cff4bafSAndreas Gohr { 1009cff4bafSAndreas Gohr $handle = fopen('php://output', 'w'); 1019cff4bafSAndreas Gohr if ($handle === false) { 1029cff4bafSAndreas Gohr $this->error('Could not open output for CSV.'); 1039cff4bafSAndreas Gohr return; 1049cff4bafSAndreas Gohr } 1059cff4bafSAndreas Gohr 106*bd0f08c8SAndreas Gohr $header = array_merge(['extension'], array_keys(reset($result))); 1079cff4bafSAndreas Gohr fputcsv($handle, $header); 1089cff4bafSAndreas Gohr 1099cff4bafSAndreas Gohr foreach ($result as $ext => $data) { 110*bd0f08c8SAndreas Gohr fputcsv($handle, array_merge([$ext], $data)); 1119cff4bafSAndreas Gohr } 1129cff4bafSAndreas Gohr } 1139cff4bafSAndreas Gohr 1149cff4bafSAndreas Gohr /** 1159cff4bafSAndreas Gohr * Output statistics as table 1169cff4bafSAndreas Gohr */ 1179cff4bafSAndreas Gohr private function print_table(array $result): void 1189cff4bafSAndreas Gohr { 119*bd0f08c8SAndreas Gohr $colWidth = 9; 120*bd0f08c8SAndreas Gohr 121*bd0f08c8SAndreas Gohr $headers = array_merge(['ext'], array_keys(reset($result))); 122*bd0f08c8SAndreas Gohr $widths = array_merge(['*'], array_fill(0, count($headers) -1, $colWidth)); 123*bd0f08c8SAndreas Gohr $colors = array_fill(0, count($headers), ''); 124*bd0f08c8SAndreas Gohr 125*bd0f08c8SAndreas Gohr // ensure terminal is wide enough, otherwise break ugly 126a3092f6cSAndreas Gohr $tr = new TableFormatter($this->colors); 127*bd0f08c8SAndreas Gohr if($tr->getMaxWidth() < $colWidth * count($headers)){; 128*bd0f08c8SAndreas Gohr $tr->setMaxWidth($colWidth * count($headers) + 10); 129*bd0f08c8SAndreas Gohr } 130*bd0f08c8SAndreas Gohr 131*bd0f08c8SAndreas Gohr echo $tr->format($widths, $headers, $colors); 132a3092f6cSAndreas Gohr 133a3092f6cSAndreas Gohr foreach ($result as $ext => $data) { 134*bd0f08c8SAndreas Gohr array_walk( 135*bd0f08c8SAndreas Gohr $data, 136*bd0f08c8SAndreas Gohr fn (&$v, $k) => $v = sprintf( 137*bd0f08c8SAndreas Gohr "% ${colWidth}s", 138*bd0f08c8SAndreas Gohr ($k == 'size') ? filesize_h($v) : number_format($v) 139*bd0f08c8SAndreas Gohr ) 140*bd0f08c8SAndreas Gohr ); 141*bd0f08c8SAndreas Gohr 1429cff4bafSAndreas Gohr echo $tr->format( 143*bd0f08c8SAndreas Gohr $widths, 144*bd0f08c8SAndreas Gohr array_merge([$ext], array_values($data)), 145*bd0f08c8SAndreas Gohr $colors 146a3092f6cSAndreas Gohr ); 147a3092f6cSAndreas Gohr } 148a3092f6cSAndreas Gohr } 149a3092f6cSAndreas Gohr} 150