1<?php
2
3/**
4 * Class helper_plugin_deletehistory
5 */
6class helper_plugin_deletehistory extends DokuWiki_Plugin
7{
8
9    /**
10     * @var array
11     */
12    protected $dirs = [];
13
14    public function __construct()
15    {
16        global $conf;
17        $this->dirs = [
18            'pages' => DOKU_INC . $conf['savedir'] . '/attic',
19            'media' => DOKU_INC . $conf['savedir'] . '/media_attic',
20        ];
21    }
22
23    /**
24     * Delete old revisions and logged changes
25     */
26    public function deleteAllHistory()
27    {
28        foreach ($this->dirs as $dir => $attic) {
29            $this->clearAttic($attic);
30            $this->deleteChanges($dir);
31        }
32        $this->cleanupChangelogs();
33    }
34
35    /**
36     * Delete everything in the given directory
37     *
38     * @param string $dir
39     */
40    protected function clearAttic($dir)
41    {
42        if (!is_readable($dir) || !is_dir($dir)) {
43            return;
44        }
45
46        $rii = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir), RecursiveIteratorIterator::CHILD_FIRST);
47
48        // delete all files
49        /** @var SplFileInfo $file */
50        foreach ($rii as $file) {
51            if (!$file->isDir()) {
52                unlink($file->getPathname());
53            }
54        }
55
56        // delete all the emptied directories
57        $rii->rewind();
58        foreach ($rii as $file) {
59            if ($file->isDir() && !in_array($file->getFilename(), ['.', '..'])) {
60                rmdir($file->getPathname());
61            }
62        }
63    }
64
65    /**
66     * Recursively find all .changes files in a directory and truncate them
67     * leaving only the first line (create event).
68     *
69     * @param string $dir "pages" or "media"
70     */
71    protected function deleteChanges($dir)
72    {
73        global $conf;
74        $metaDir = ($dir === 'media') ? 'media_meta' : 'meta';
75        $path = DOKU_INC . $conf['savedir'] . '/' . $metaDir;
76        if (!file_exists($path) || !is_dir($path)) return;
77
78        $rii = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path));
79
80        /** @var SplFileInfo $file */
81        foreach ($rii as $file) {
82            if (!$file->isDir() && $file->getExtension() === 'changes' && $file->getFilename()[0] !== '_') {
83                $currentLog = @file($file->getPathname());
84                if (!$currentLog) {
85                    continue;
86                }
87                $updatedLog = substr_replace($currentLog[0], filemtime($file->getPathname()), 0, 10);
88                io_saveFile($file->getPathname(), $updatedLog);
89            }
90        }
91    }
92
93    /**
94     * Delete from global changelogs all changes except create
95     */
96    protected function cleanupChangelogs()
97    {
98        global $conf;
99
100        // filter lines on "C"
101        $pattern = "/^\d{10}\t[0-9\.]*\t[^C]\t/";
102        io_replaceInFile($conf['changelog'], $pattern, '', true);
103        io_replaceInFile($conf['media_changelog'], $pattern, '', true);
104    }
105}
106