1<?php
2/**
3 * Move Plugin File Mover
4 *
5 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
6 * @author     Michael Hamann <michael@content-space.de>
7 * @author     Andreas Gohr <gohr@cosmocode.de>
8 */
9// must be run within Dokuwiki
10if(!defined('DOKU_INC')) die();
11
12/**
13 * Class helper_plugin_move_file
14 *
15 * This helps with moving files from one folder to another. It simply matches files and moves them
16 * arround. No fancy rewriting happens here.
17 */
18class helper_plugin_move_file extends DokuWiki_Plugin {
19
20    /**
21     * Move the meta files of a page
22     *
23     * @param string $src_ns   The original namespace
24     * @param string $src_name The original basename of the moved doc (empty for namespace moves)
25     * @param string $dst_ns   The namespace after the move
26     * @param string $dst_name The basename after the move (empty for namespace moves)
27     * @return bool If the meta files were moved successfully
28     */
29    public function movePageMeta($src_ns, $src_name, $dst_ns, $dst_name) {
30        global $conf;
31
32        $regex = '\.[^.]+';
33        return $this->execute($conf['metadir'], $src_ns, $src_name, $dst_ns, $dst_name, $regex);
34    }
35
36    /**
37     * Move the old revisions of a page
38     *
39     * @param string $src_ns   The original namespace
40     * @param string $src_name The original basename of the moved doc (empty for namespace moves)
41     * @param string $dst_ns   The namespace after the move
42     * @param string $dst_name The basename after the move (empty for namespace moves)
43     * @return bool If the attic files were moved successfully
44     */
45    public function movePageAttic($src_ns, $src_name, $dst_ns, $dst_name) {
46        global $conf;
47
48        $regex = '\.\d+\.txt(?:\.gz|\.bz2)?';
49        return $this->execute($conf['olddir'], $src_ns, $src_name, $dst_ns, $dst_name, $regex);
50    }
51
52    /**
53     * Move the meta files of the page that is specified in the options.
54     *
55     * @param string $src_ns   The original namespace
56     * @param string $src_name The original basename of the moved doc (empty for namespace moves)
57     * @param string $dst_ns   The namespace after the move
58     * @param string $dst_name The basename after the move (empty for namespace moves)
59     * @return bool If the meta files were moved successfully
60     */
61    public function moveMediaMeta($src_ns, $src_name, $dst_ns, $dst_name) {
62        global $conf;
63
64        $regex = '\.[^.]+';
65        return $this->execute($conf['mediametadir'], $src_ns, $src_name, $dst_ns, $dst_name, $regex);
66    }
67
68    /**
69     * Move the old revisions of the media file that is specified in the options
70     *
71     * @param string $src_ns   The original namespace
72     * @param string $src_name The original basename of the moved doc (empty for namespace moves)
73     * @param string $dst_ns   The namespace after the move
74     * @param string $dst_name The basename after the move (empty for namespace moves)
75     * @return bool If the attic files were moved successfully
76     */
77    public function moveMediaAttic($src_ns, $src_name, $dst_ns, $dst_name) {
78        global $conf;
79
80        $ext = mimetype($src_name);
81        if($ext[0] !== false) {
82            $name = substr($src_name, 0, -1 * strlen($ext[0]) - 1);
83        } else {
84            $name = $src_name;
85        }
86        $newext = mimetype($dst_name);
87        if($newext[0] !== false) {
88            $newname = substr($dst_name, 0, -1 * strlen($newext[0]) - 1);
89        } else {
90            $newname = $dst_name;
91        }
92        $regex = '\.\d+\.' . preg_quote((string) $ext[0], '/');
93
94        return $this->execute($conf['mediaolddir'], $src_ns, $name, $dst_ns, $newname, $regex);
95    }
96
97    /**
98     * Moves the subscription file for a namespace
99     *
100     * @param string $src_ns
101     * @param string $dst_ns
102     * @return bool
103     */
104    public function moveNamespaceSubscription($src_ns, $dst_ns){
105        global $conf;
106
107        $regex = '\.mlist';
108        return $this->execute($conf['metadir'], $src_ns, '', $dst_ns, '', $regex);
109    }
110
111    /**
112     * Executes the move op
113     *
114     * @param string $dir      The root path of the files (e.g. $conf['metadir'] or $conf['olddir']
115     * @param string $src_ns   The original namespace
116     * @param string $src_name The original basename of the moved doc (empty for namespace moves)
117     * @param string $dst_ns   The namespace after the move
118     * @param string $dst_name The basename after the move (empty for namespace moves)
119     * @param string $extregex Regular expression for matching the extension of the file that shall be moved
120     * @return bool If the files were moved successfully
121     */
122    protected function execute($dir, $src_ns, $src_name, $dst_ns, $dst_name, $extregex) {
123        $old_path = $dir;
124        if($src_ns != '') $old_path .= '/' . utf8_encodeFN(str_replace(':', '/', $src_ns));
125        $new_path = $dir;
126        if($dst_ns != '') $new_path .= '/' . utf8_encodeFN(str_replace(':', '/', $dst_ns));
127        $regex = '/^' . preg_quote(utf8_encodeFN($src_name)) . '(' . $extregex . ')$/u';
128
129        if(!is_dir($old_path)) return true; // no media files found
130
131        $dh = @opendir($old_path);
132        if($dh) {
133            while(($file = readdir($dh)) !== false) {
134                if($file == '.' || $file == '..') continue;
135                $match = array();
136                if(is_file($old_path . '/' . $file) && preg_match($regex, $file, $match)) {
137                    if(!is_dir($new_path)) {
138                        if(!io_mkdir_p($new_path)) {
139                            msg('Creating directory ' . hsc($new_path) . ' failed.', -1);
140                            return false;
141                        }
142                    }
143                    if(!io_rename($old_path . '/' . $file, $new_path . '/' . utf8_encodeFN($dst_name . $match[1]))) {
144                        msg('Moving ' . hsc($old_path . '/' . $file) . ' to ' . hsc($new_path . '/' . utf8_encodeFN($dst_name . $match[1])) . ' failed.', -1);
145                        return false;
146                    }
147                }
148            }
149            closedir($dh);
150        } else {
151            msg('Directory ' . hsc($old_path) . ' couldn\'t be opened.', -1);
152            return false;
153        }
154        return true;
155    }
156}