1<?php
2/**
3 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
4 * @author     Esther Brunner <wikidesign@gmail.com>
5 */
6
7/* ----- Settings ----- */
8
9define('DOKU_INC', realpath(dirname(__FILE__) . '/../../../') . '/');
10const DISCUSSION_NS = 'discussion';
11
12/* ----- Main ----- */
13
14// conversion script should only be run once
15if (@file_exists(dirname(__FILE__) . '/convert_completed')) {
16    die('Conversion already completed.');
17}
18
19require_once(DOKU_INC . 'inc/init.php');
20
21$files = getDiscussionPages();
22$n = 0;
23
24foreach ($files as $file) {
25    if (convertDiscussionPage($file)) {
26        echo $file['id'] . '<br />';
27        $n++;
28    }
29}
30
31if ($n > 0) {
32    io_saveFile(dirname(__FILE__) . '/convert_completed', '');
33    echo '<br />Successfully converted ' . $n . ' discussion pages to new comments meta files.';
34} else {
35    echo 'No discussion pages found.';
36}
37
38/* ----- Functions ----- */
39
40/**
41 * returns a list of all discussion pages in the wiki
42 */
43function getDiscussionPages()
44{
45    global $conf;
46
47    $data = [];
48    search($data, $conf['datadir'], 'search_discussionpages', []);
49    return $data;
50}
51
52/**
53 * function for the search callback
54 */
55function search_discussionpages(&$data, $base, $file, $type, $lvl, $opts)
56{
57    global $conf;
58
59    // recurse into directories
60    if ($type == 'd') {
61        return true;
62    }
63    if (!preg_match('#' . preg_quote('/' . DISCUSSION_NS . '/', '#') . '#u', $file)) {
64        return false;
65    }
66    if (!preg_match('#\.txt$#', $file)) {
67        return false;
68    }
69
70    $id = pathID(str_replace(DISCUSSION_NS . '/', '', $file));
71    $data[] = [
72        'id' => $id,
73        'old' => $conf['datadir'] . $file,
74        'new' => metaFN($id, '.comments')
75    ];
76    return true;
77}
78
79/**
80 * this converts individual discussion pages to .comment meta files
81 */
82function convertDiscussionPage($file)
83{
84
85    // read the old file
86    $data = io_readFile($file['old'], false);
87
88    // handle file with no comments yet
89    if (trim($data) == '') {
90        io_saveFile($file['new'], serialize(['status' => 1, 'number' => 0]));
91        @unlink($file['old']);
92        return true;
93    }
94
95    // break it up into pieces
96    $old = explode('----', $data);
97
98    // merge with possibly already existing (newer) comments
99    $comments = [];
100    if (@file_exists($file['new'])) {
101        $comments = unserialize(io_readFile($file['old'], false));
102    }
103
104    // set general info
105    if (!isset($comments['status'])) {
106        $comments['status'] = 1;
107    }
108    $comments['number'] += count($old);
109
110    foreach ($old as $comment) {
111
112        // prepare comment data
113        if (strpos($comment, '<sub>') !== false) {
114            $in = '<sub>';
115            $out = ':</sub>';
116        } else {
117            $in = '//';
118            $out = ': //';
119        }
120        list($meta, $raw) = array_pad(explode($out, $comment, 2), 2, '');
121        $raw = trim($raw);
122
123        // skip empty comments
124        if (!$raw) {
125            $comments['number']--;
126            continue;
127        }
128
129        list($mail, $meta) = array_pad(explode($in, $meta, 2), 2, '');
130        list($name, $strd) = array_pad(explode(', ', $meta, 2), 2, '');
131        $date = strtotime($strd);
132        if ($date == -1) {
133            $date = time();
134        }
135        if ($mail) {
136            list($mail) = array_pad(explode(' |', $mail, 2), 2, '');
137            $mail = substr(strrchr($mail, '>'), 1);
138        }
139        $cid = md5($name . $date);
140
141        // render comment
142        $xhtml = p_render('xhtml', p_get_instructions($raw), $info);
143
144        // fill in the converted comment
145        $comments['comments'][$cid] = [
146            'user' => [
147                'name' => hsc($name),
148                'mail' => hsc($mail)],
149            'date' => ['created' => $date],
150            'show' => true,
151            'raw' => $raw,
152            'xhtml' => $xhtml,
153            'replies' => []
154        ];
155    }
156
157    // save the new file
158    io_saveFile($file['new'], serialize($comments));
159
160    // remove the old file
161    @unlink($file['old']);
162
163    return true;
164}
165