xref: /plugin/cachestats/cli.php (revision a6282b4305194b4d4422ae419e63e95f58f1bbef)
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