xref: /plugin/cachestats/cli.php (revision 9cff4baf4483a5045edcf0548c0d44e79eeda979)
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{
15*9cff4bafSAndreas Gohr    /** @var string[] */
16*9cff4bafSAndreas Gohr    private array $buckets = ['<1d', '<1w', '<1m', '<3m', '<6m', '<1y', '>1y'];
17*9cff4bafSAndreas 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
23*9cff4bafSAndreas 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
38*9cff4bafSAndreas Gohr        $format = $options->getOpt('format', 'table');
39*9cff4bafSAndreas Gohr        if (!in_array($format, ['table', 'json', 'csv'])) {
40*9cff4bafSAndreas Gohr            $this->error("Invalid format option '$format'. Allowed are: table, json, csv.");
41*9cff4bafSAndreas Gohr            return 1;
42*9cff4bafSAndreas Gohr        }
43*9cff4bafSAndreas Gohr
44*9cff4bafSAndreas 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) {
64*9cff4bafSAndreas Gohr            $modified = [];
65*9cff4bafSAndreas Gohr            foreach ($this->buckets as $bucket) {
66*9cff4bafSAndreas Gohr                $modified[$bucket] = $stats['modified_groups'][$key][$bucket] ?? 0;
67*9cff4bafSAndreas Gohr            }
68a3092f6cSAndreas Gohr            $result[$key] = [
69a3092f6cSAndreas Gohr                'count' => $stats['extensions'][$key] ?? 0,
70a3092f6cSAndreas Gohr                'size' => $stats['sizes'][$key] ?? 0,
71a3092f6cSAndreas Gohr                'dups' => $stats['duplicates'][$key] ?? 0,
72*9cff4bafSAndreas Gohr                'modified' => $modified,
73a3092f6cSAndreas Gohr            ];
74a3092f6cSAndreas Gohr        }
75a3092f6cSAndreas Gohr
76a3092f6cSAndreas Gohr        // sort with preserved keys
77a3092f6cSAndreas Gohr        uasort($result, function ($a, $b) use ($sort) {
78a3092f6cSAndreas Gohr            return $b[$sort] <=> $a[$sort];
79a3092f6cSAndreas Gohr        });
80a3092f6cSAndreas Gohr
81*9cff4bafSAndreas Gohr        match ($format) {
82*9cff4bafSAndreas Gohr            'json' => $this->print_json($result),
83*9cff4bafSAndreas Gohr            'csv' => $this->print_csv($result),
84*9cff4bafSAndreas Gohr            default => $this->print_table($result),
85*9cff4bafSAndreas Gohr        };
86a3092f6cSAndreas Gohr        return 0;
87a3092f6cSAndreas Gohr    }
88a3092f6cSAndreas Gohr
89*9cff4bafSAndreas Gohr    /**
90*9cff4bafSAndreas Gohr     * Output statistics as JSON
91*9cff4bafSAndreas Gohr     */
92*9cff4bafSAndreas Gohr    private function print_json(array $result): void
93*9cff4bafSAndreas Gohr    {
94*9cff4bafSAndreas Gohr        echo json_encode($result, JSON_PRETTY_PRINT);
95*9cff4bafSAndreas Gohr    }
96*9cff4bafSAndreas Gohr
97*9cff4bafSAndreas Gohr    /**
98*9cff4bafSAndreas Gohr     * Output statistics as CSV
99*9cff4bafSAndreas Gohr     */
100*9cff4bafSAndreas Gohr    private function print_csv(array $result): void
101*9cff4bafSAndreas Gohr    {
102*9cff4bafSAndreas Gohr        $handle = fopen('php://output', 'w');
103*9cff4bafSAndreas Gohr        if ($handle === false) {
104*9cff4bafSAndreas Gohr            $this->error('Could not open output for CSV.');
105*9cff4bafSAndreas Gohr            return;
106*9cff4bafSAndreas Gohr        }
107*9cff4bafSAndreas Gohr
108*9cff4bafSAndreas Gohr        $header = array_merge(
109*9cff4bafSAndreas Gohr            ['extension', 'count', 'total_size_bytes', 'duplicate_files'],
110*9cff4bafSAndreas Gohr            $this->buckets
111*9cff4bafSAndreas Gohr        );
112*9cff4bafSAndreas Gohr        fputcsv($handle, $header);
113*9cff4bafSAndreas Gohr
114*9cff4bafSAndreas Gohr        foreach ($result as $ext => $data) {
115*9cff4bafSAndreas Gohr            $row = [
116*9cff4bafSAndreas Gohr                $ext,
117*9cff4bafSAndreas Gohr                $data['count'],
118*9cff4bafSAndreas Gohr                $data['size'],
119*9cff4bafSAndreas Gohr                $data['dups']
120*9cff4bafSAndreas Gohr            ];
121*9cff4bafSAndreas Gohr            foreach ($this->buckets as $bucket) {
122*9cff4bafSAndreas Gohr                $row[] = $data['modified'][$bucket];
123*9cff4bafSAndreas Gohr            }
124*9cff4bafSAndreas Gohr            fputcsv($handle, $row);
125*9cff4bafSAndreas Gohr        }
126*9cff4bafSAndreas Gohr    }
127*9cff4bafSAndreas Gohr
128*9cff4bafSAndreas Gohr    /**
129*9cff4bafSAndreas Gohr     * Output statistics as table
130*9cff4bafSAndreas Gohr     */
131*9cff4bafSAndreas Gohr    private function print_table(array $result): void
132*9cff4bafSAndreas Gohr    {
133a3092f6cSAndreas Gohr        $tr = new TableFormatter($this->colors);
134*9cff4bafSAndreas Gohr        $columns = array_merge(['*', 7, 10, 7], array_fill(0, count($this->buckets), 5));
135*9cff4bafSAndreas Gohr        $headers = array_merge(
136a3092f6cSAndreas Gohr            ['Extension', 'File Count', 'Total Size (bytes)', 'Duplicate Files'],
137*9cff4bafSAndreas Gohr            $this->buckets
138*9cff4bafSAndreas Gohr        );
139*9cff4bafSAndreas Gohr        echo $tr->format(
140*9cff4bafSAndreas Gohr            $columns,
141*9cff4bafSAndreas Gohr            $headers,
142a3092f6cSAndreas Gohr            ['', '', '', '']
143a3092f6cSAndreas Gohr        );
144a3092f6cSAndreas Gohr
145a3092f6cSAndreas Gohr        foreach ($result as $ext => $data) {
146*9cff4bafSAndreas Gohr            $row = [
147a3092f6cSAndreas Gohr                $ext,
148*9cff4bafSAndreas Gohr                sprintf("% 7s", number_format($data['count'])),
149a3092f6cSAndreas Gohr                sprintf("% 10s", filesize_h($data['size'])),
150*9cff4bafSAndreas Gohr                sprintf("% 7s", number_format($data['dups']))
151*9cff4bafSAndreas Gohr            ];
152*9cff4bafSAndreas Gohr            foreach ($this->buckets as $bucket) {
153*9cff4bafSAndreas Gohr                $row[] = sprintf("% 5s", number_format($data['modified'][$bucket]));
154*9cff4bafSAndreas Gohr            }
155*9cff4bafSAndreas Gohr            echo $tr->format(
156*9cff4bafSAndreas Gohr                $columns,
157*9cff4bafSAndreas Gohr                $row,
158a3092f6cSAndreas Gohr                ['', '', '', '']
159a3092f6cSAndreas Gohr            );
160a3092f6cSAndreas Gohr        }
161a3092f6cSAndreas Gohr    }
162a3092f6cSAndreas Gohr}
163