1<?php 2 3use dokuwiki\plugin\cachestats\FileStatistics; 4use splitbrain\phpcli\Options; 5use splitbrain\phpcli\TableFormatter; 6 7/** 8 * DokuWiki Plugin cachestats (CLI Component) 9 * 10 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 11 * @author Andreas Gohr <andi@splitbrain.org> 12 */ 13class cli_plugin_cachestats extends \dokuwiki\Extension\CLIPlugin 14{ 15 /** @inheritDoc */ 16 protected function setup(Options $options) 17 { 18 $options->setHelp('Collect statistics about the cache directory.'); 19 20 $options->registerOption('noprogress', 'Don\'t show progress dots'); 21 $options->registerOption('format', 'Output format. Defaults to table.', 'f', 'table|json|csv'); 22 $options->registerOption('sort', 'Sort by this criteria. Defaults to size.', 's', 'count|size|dups'); 23 } 24 25 /** @inheritDoc */ 26 protected function main(Options $options) 27 { 28 global $conf; 29 30 $sort = $options->getOpt('sort', 'size'); 31 if (!in_array($sort, ['count', 'size', 'dups'])) { 32 $this->error("Invalid sort option '$sort'. Allowed are: count, size, dups."); 33 return 1; 34 } 35 36 $format = $options->getOpt('format', 'table'); 37 if (!in_array($format, ['table', 'json', 'csv'])) { 38 $this->error("Invalid format option '$format'. Allowed are: table, json, csv."); 39 return 1; 40 } 41 42 // progress report - collecting stats can take a while 43 fprintf(STDERR, 'Collecting cache statistics from ' . $conf['cachedir'] . "…\n"); 44 if(!$options->getOpt('noprogress')) { 45 $cb = function($count) { 46 if ($count % 50000 === 0) { 47 fprintf(STDERR, "%s files processed\n", number_format($count)); 48 } elseif ($count % 1000 === 0) { 49 fprintf(STDERR, "."); 50 } 51 }; 52 } else { 53 $cb = null; 54 } 55 56 $result = (new FileStatistics($conf['cachedir']))->collect($cb); 57 if($cb) fprintf(STDERR, "\n"); 58 59 // sort with preserved keys 60 uasort($result, function ($a, $b) use ($sort) { 61 return $b[$sort] <=> $a[$sort]; 62 }); 63 64 match ($format) { 65 'json' => $this->print_json($result), 66 'csv' => $this->print_csv($result), 67 default => $this->print_table($result), 68 }; 69 return 0; 70 } 71 72 /** 73 * Output statistics as JSON 74 */ 75 private function print_json(array $result): void 76 { 77 echo json_encode($result, JSON_PRETTY_PRINT); 78 } 79 80 /** 81 * Output statistics as CSV 82 */ 83 private function print_csv(array $result): void 84 { 85 $handle = fopen('php://output', 'w'); 86 if ($handle === false) { 87 $this->error('Could not open output for CSV.'); 88 return; 89 } 90 91 $header = array_merge(['extension'], array_keys(reset($result))); 92 fputcsv($handle, $header); 93 94 foreach ($result as $ext => $data) { 95 fputcsv($handle, array_merge([$ext], $data)); 96 } 97 } 98 99 /** 100 * Output statistics as table 101 */ 102 private function print_table(array $result): void 103 { 104 $colWidth = 9; 105 106 $headers = array_merge(['ext'], array_keys(reset($result))); 107 $widths = array_merge(['*'], array_fill(0, count($headers) -1, $colWidth)); 108 $colors = array_fill(0, count($headers), ''); 109 110 // ensure terminal is wide enough, otherwise break ugly 111 $tr = new TableFormatter($this->colors); 112 if($tr->getMaxWidth() < $colWidth * count($headers)){; 113 $tr->setMaxWidth($colWidth * count($headers) + 10); 114 } 115 116 echo $tr->format($widths, $headers, $colors); 117 118 foreach ($result as $ext => $data) { 119 array_walk( 120 $data, 121 fn (&$v, $k) => $v = sprintf( 122 "% ${colWidth}s", 123 ($k == 'size') ? filesize_h($v) : number_format($v) 124 ) 125 ); 126 127 echo $tr->format( 128 $widths, 129 array_merge([$ext], array_values($data)), 130 $colors 131 ); 132 } 133 } 134} 135