xref: /plugin/cachestats/cli.php (revision 9cff4baf4483a5045edcf0548c0d44e79eeda979)
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    /** @var string[] */
16    private array $buckets = ['<1d', '<1w', '<1m', '<3m', '<6m', '<1y', '>1y'];
17
18    /** @inheritDoc */
19    protected function setup(Options $options)
20    {
21        $options->setHelp('Collect statistics about the cache directory.');
22
23        $options->registerOption('format', 'Output format: table|json|csv', 'f', 'table');
24        $options->registerOption('sort', 'Sort by count|size|dups', 's', false);
25    }
26
27    /** @inheritDoc */
28    protected function main(Options $options)
29    {
30        global $conf;
31
32        $sort = $options->getOpt('sort', 'size');
33        if (!in_array($sort, ['count', 'size', 'dups'])) {
34            $this->error("Invalid sort option '$sort'. Allowed are: count, size, dups.");
35            return 1;
36        }
37
38        $format = $options->getOpt('format', 'table');
39        if (!in_array($format, ['table', 'json', 'csv'])) {
40            $this->error("Invalid format option '$format'. Allowed are: table, json, csv.");
41            return 1;
42        }
43
44        if ($format === 'json') {
45            fprintf(STDERR, 'Collecting cache statistics from ' . $conf['cachedir'] . "…\n");
46        } else {
47            $this->info('Collecting cache statistics from ' . $conf['cachedir'] . '…');
48        }
49
50        $stats = (new FileStatistics($conf['cachedir']))->collect();
51
52        // for debugging
53        print_r($stats);
54
55        $keys = array_unique(
56            array_merge(
57                array_keys($stats['extensions']),
58                array_keys($stats['sizes']),
59                array_keys($stats['duplicates'])
60            )
61        );
62        $result = [];
63        foreach ($keys as $key) {
64            $modified = [];
65            foreach ($this->buckets as $bucket) {
66                $modified[$bucket] = $stats['modified_groups'][$key][$bucket] ?? 0;
67            }
68            $result[$key] = [
69                'count' => $stats['extensions'][$key] ?? 0,
70                'size' => $stats['sizes'][$key] ?? 0,
71                'dups' => $stats['duplicates'][$key] ?? 0,
72                'modified' => $modified,
73            ];
74        }
75
76        // sort with preserved keys
77        uasort($result, function ($a, $b) use ($sort) {
78            return $b[$sort] <=> $a[$sort];
79        });
80
81        match ($format) {
82            'json' => $this->print_json($result),
83            'csv' => $this->print_csv($result),
84            default => $this->print_table($result),
85        };
86        return 0;
87    }
88
89    /**
90     * Output statistics as JSON
91     */
92    private function print_json(array $result): void
93    {
94        echo json_encode($result, JSON_PRETTY_PRINT);
95    }
96
97    /**
98     * Output statistics as CSV
99     */
100    private function print_csv(array $result): void
101    {
102        $handle = fopen('php://output', 'w');
103        if ($handle === false) {
104            $this->error('Could not open output for CSV.');
105            return;
106        }
107
108        $header = array_merge(
109            ['extension', 'count', 'total_size_bytes', 'duplicate_files'],
110            $this->buckets
111        );
112        fputcsv($handle, $header);
113
114        foreach ($result as $ext => $data) {
115            $row = [
116                $ext,
117                $data['count'],
118                $data['size'],
119                $data['dups']
120            ];
121            foreach ($this->buckets as $bucket) {
122                $row[] = $data['modified'][$bucket];
123            }
124            fputcsv($handle, $row);
125        }
126    }
127
128    /**
129     * Output statistics as table
130     */
131    private function print_table(array $result): void
132    {
133        $tr = new TableFormatter($this->colors);
134        $columns = array_merge(['*', 7, 10, 7], array_fill(0, count($this->buckets), 5));
135        $headers = array_merge(
136            ['Extension', 'File Count', 'Total Size (bytes)', 'Duplicate Files'],
137            $this->buckets
138        );
139        echo $tr->format(
140            $columns,
141            $headers,
142            ['', '', '', '']
143        );
144
145        foreach ($result as $ext => $data) {
146            $row = [
147                $ext,
148                sprintf("% 7s", number_format($data['count'])),
149                sprintf("% 10s", filesize_h($data['size'])),
150                sprintf("% 7s", number_format($data['dups']))
151            ];
152            foreach ($this->buckets as $bucket) {
153                $row[] = sprintf("% 5s", number_format($data['modified'][$bucket]));
154            }
155            echo $tr->format(
156                $columns,
157                $row,
158                ['', '', '', '']
159            );
160        }
161    }
162}
163