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