indentation fix in media.php
[dokuwiki.git] / inc / changelog.php
blobaf147b7e000178a0c4087437ec86af0d828362ff
1 <?php
3 /**
4 * Changelog handling functions
6 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
7 * @author Andreas Gohr <andi@splitbrain.org>
8 */
10 use dokuwiki\ChangeLog\MediaChangeLog;
11 use dokuwiki\ChangeLog\ChangeLog;
12 use dokuwiki\File\PageFile;
14 /**
15 * parses a changelog line into it's components
17 * @author Ben Coburn <btcoburn@silicodon.net>
19 * @param string $line changelog line
20 * @return array|bool parsed line or false
22 function parseChangelogLine($line)
24 return ChangeLog::parseLogLine($line);
27 /**
28 * Adds an entry to the changelog and saves the metadata for the page
30 * Note: timestamp of the change might not be unique especially after very quick
31 * repeated edits (e.g. change checkbox via do plugin)
33 * @param int $date Timestamp of the change
34 * @param String $id Name of the affected page
35 * @param String $type Type of the change see DOKU_CHANGE_TYPE_*
36 * @param String $summary Summary of the change
37 * @param mixed $extra In case of a revert the revision (timestamp) of the reverted page
38 * @param array $flags Additional flags in a key value array.
39 * Available flags:
40 * - ExternalEdit - mark as an external edit.
41 * @param null|int $sizechange Change of filesize
43 * @author Andreas Gohr <andi@splitbrain.org>
44 * @author Esther Brunner <wikidesign@gmail.com>
45 * @author Ben Coburn <btcoburn@silicodon.net>
46 * @deprecated 2021-11-28
48 function addLogEntry(
49 $date,
50 $id,
51 $type = DOKU_CHANGE_TYPE_EDIT,
52 $summary = '',
53 $extra = '',
54 $flags = null,
55 $sizechange = null
56 ) {
57 // no more used in DokuWiki core, but left for third-party plugins
58 dbg_deprecated('see ' . PageFile::class . '::saveWikiText()');
60 /** @var Input $INPUT */
61 global $INPUT;
63 // check for special flags as keys
64 if (!is_array($flags)) $flags = [];
65 $flagExternalEdit = isset($flags['ExternalEdit']);
67 $id = cleanid($id);
69 if (!$date) $date = time(); //use current time if none supplied
70 $remote = ($flagExternalEdit) ? '127.0.0.1' : clientIP(true);
71 $user = ($flagExternalEdit) ? '' : $INPUT->server->str('REMOTE_USER');
72 $sizechange = ($sizechange === null) ? '' : (int)$sizechange;
74 // update changelog file and get the added entry that is also to be stored in metadata
75 $pageFile = new PageFile($id);
76 $logEntry = $pageFile->changelog->addLogEntry([
77 'date' => $date,
78 'ip' => $remote,
79 'type' => $type,
80 'id' => $id,
81 'user' => $user,
82 'sum' => $summary,
83 'extra' => $extra,
84 'sizechange' => $sizechange,
85 ]);
87 // update metadata
88 $pageFile->updateMetadata($logEntry);
91 /**
92 * Adds an entry to the media changelog
94 * @author Michael Hamann <michael@content-space.de>
95 * @author Andreas Gohr <andi@splitbrain.org>
96 * @author Esther Brunner <wikidesign@gmail.com>
97 * @author Ben Coburn <btcoburn@silicodon.net>
99 * @param int $date Timestamp of the change
100 * @param String $id Name of the affected page
101 * @param String $type Type of the change see DOKU_CHANGE_TYPE_*
102 * @param String $summary Summary of the change
103 * @param mixed $extra In case of a revert the revision (timestamp) of the reverted page
104 * @param array $flags Additional flags in a key value array.
105 * Available flags:
106 * - (none, so far)
107 * @param null|int $sizechange Change of filesize
109 function addMediaLogEntry(
110 $date,
111 $id,
112 $type = DOKU_CHANGE_TYPE_EDIT,
113 $summary = '',
114 $extra = '',
115 $flags = null,
116 $sizechange = null
118 /** @var Input $INPUT */
119 global $INPUT;
121 // check for special flags as keys
122 if (!is_array($flags)) $flags = [];
123 $flagExternalEdit = isset($flags['ExternalEdit']);
125 $id = cleanid($id);
127 if (!$date) $date = time(); //use current time if none supplied
128 $remote = ($flagExternalEdit) ? '127.0.0.1' : clientIP(true);
129 $user = ($flagExternalEdit) ? '' : $INPUT->server->str('REMOTE_USER');
130 $sizechange = ($sizechange === null) ? '' : (int)$sizechange;
132 // update changelog file and get the added entry
133 (new MediaChangeLog($id, 1024))->addLogEntry([
134 'date' => $date,
135 'ip' => $remote,
136 'type' => $type,
137 'id' => $id,
138 'user' => $user,
139 'sum' => $summary,
140 'extra' => $extra,
141 'sizechange' => $sizechange,
146 * returns an array of recently changed files using the changelog
148 * The following constants can be used to control which changes are
149 * included. Add them together as needed.
151 * RECENTS_SKIP_DELETED - don't include deleted pages
152 * RECENTS_SKIP_MINORS - don't include minor changes
153 * RECENTS_ONLY_CREATION - only include new created pages and media
154 * RECENTS_SKIP_SUBSPACES - don't include subspaces
155 * RECENTS_MEDIA_CHANGES - return media changes instead of page changes
156 * RECENTS_MEDIA_PAGES_MIXED - return both media changes and page changes
158 * @param int $first number of first entry returned (for paginating
159 * @param int $num return $num entries
160 * @param string $ns restrict to given namespace
161 * @param int $flags see above
162 * @return array recently changed files
164 * @author Ben Coburn <btcoburn@silicodon.net>
165 * @author Kate Arzamastseva <pshns@ukr.net>
167 function getRecents($first, $num, $ns = '', $flags = 0)
169 global $conf;
170 $recent = [];
171 $count = 0;
173 if (!$num)
174 return $recent;
176 // read all recent changes. (kept short)
177 if ($flags & RECENTS_MEDIA_CHANGES) {
178 $lines = @file($conf['media_changelog']) ?: [];
179 } else {
180 $lines = @file($conf['changelog']) ?: [];
182 if (!is_array($lines)) {
183 $lines = [];
185 $lines_position = count($lines) - 1;
186 $media_lines_position = 0;
187 $media_lines = [];
189 if ($flags & RECENTS_MEDIA_PAGES_MIXED) {
190 $media_lines = @file($conf['media_changelog']) ?: [];
191 if (!is_array($media_lines)) {
192 $media_lines = [];
194 $media_lines_position = count($media_lines) - 1;
197 $seen = []; // caches seen lines, _handleRecent() skips them
199 // handle lines
200 while ($lines_position >= 0 || (($flags & RECENTS_MEDIA_PAGES_MIXED) && $media_lines_position >= 0)) {
201 if (empty($rec) && $lines_position >= 0) {
202 $rec = _handleRecent(@$lines[$lines_position], $ns, $flags, $seen);
203 if (!$rec) {
204 $lines_position--;
205 continue;
208 if (($flags & RECENTS_MEDIA_PAGES_MIXED) && empty($media_rec) && $media_lines_position >= 0) {
209 $media_rec = _handleRecent(
210 @$media_lines[$media_lines_position],
211 $ns,
212 $flags | RECENTS_MEDIA_CHANGES,
213 $seen
215 if (!$media_rec) {
216 $media_lines_position--;
217 continue;
220 if (($flags & RECENTS_MEDIA_PAGES_MIXED) && @$media_rec['date'] >= @$rec['date']) {
221 $media_lines_position--;
222 $x = $media_rec;
223 $x['media'] = true;
224 $media_rec = false;
225 } else {
226 $lines_position--;
227 $x = $rec;
228 if ($flags & RECENTS_MEDIA_CHANGES) {
229 $x['media'] = true;
230 } else {
231 $x['media'] = false;
233 $rec = false;
235 if (--$first >= 0) continue; // skip first entries
236 $recent[] = $x;
237 $count++;
238 // break when we have enough entries
239 if ($count >= $num) {
240 break;
243 return $recent;
247 * returns an array of files changed since a given time using the
248 * changelog
250 * The following constants can be used to control which changes are
251 * included. Add them together as needed.
253 * RECENTS_SKIP_DELETED - don't include deleted pages
254 * RECENTS_SKIP_MINORS - don't include minor changes
255 * RECENTS_ONLY_CREATION - only include new created pages and media
256 * RECENTS_SKIP_SUBSPACES - don't include subspaces
257 * RECENTS_MEDIA_CHANGES - return media changes instead of page changes
259 * @param int $from date of the oldest entry to return
260 * @param int $to date of the newest entry to return (for pagination, optional)
261 * @param string $ns restrict to given namespace (optional)
262 * @param int $flags see above (optional)
263 * @return array of files
265 * @author Michael Hamann <michael@content-space.de>
266 * @author Ben Coburn <btcoburn@silicodon.net>
268 function getRecentsSince($from, $to = null, $ns = '', $flags = 0)
270 global $conf;
271 $recent = [];
273 if ($to && $to < $from)
274 return $recent;
276 // read all recent changes. (kept short)
277 if ($flags & RECENTS_MEDIA_CHANGES) {
278 $lines = @file($conf['media_changelog']);
279 } else {
280 $lines = @file($conf['changelog']);
282 if (!$lines) return $recent;
284 // we start searching at the end of the list
285 $lines = array_reverse($lines);
287 // handle lines
288 $seen = []; // caches seen lines, _handleRecent() skips them
290 foreach ($lines as $line) {
291 $rec = _handleRecent($line, $ns, $flags, $seen);
292 if ($rec !== false) {
293 if ($rec['date'] >= $from) {
294 if (!$to || $rec['date'] <= $to) {
295 $recent[] = $rec;
297 } else {
298 break;
303 return array_reverse($recent);
307 * Internal function used by getRecents
309 * don't call directly
311 * @see getRecents()
312 * @author Andreas Gohr <andi@splitbrain.org>
313 * @author Ben Coburn <btcoburn@silicodon.net>
315 * @param string $line changelog line
316 * @param string $ns restrict to given namespace
317 * @param int $flags flags to control which changes are included
318 * @param array $seen listing of seen pages
319 * @return array|bool false or array with info about a change
321 function _handleRecent($line, $ns, $flags, &$seen)
323 if (empty($line)) return false; //skip empty lines
325 // split the line into parts
326 $recent = ChangeLog::parseLogLine($line);
327 if ($recent === false) return false;
329 // skip seen ones
330 if (isset($seen[$recent['id']])) return false;
332 // skip changes, of only new items are requested
333 if ($recent['type'] !== DOKU_CHANGE_TYPE_CREATE && ($flags & RECENTS_ONLY_CREATION)) return false;
335 // skip minors
336 if ($recent['type'] === DOKU_CHANGE_TYPE_MINOR_EDIT && ($flags & RECENTS_SKIP_MINORS)) return false;
338 // remember in seen to skip additional sights
339 $seen[$recent['id']] = 1;
341 // check if it's a hidden page
342 if (isHiddenPage($recent['id'])) return false;
344 // filter namespace
345 if (($ns) && (strpos($recent['id'], $ns . ':') !== 0)) return false;
347 // exclude subnamespaces
348 if (($flags & RECENTS_SKIP_SUBSPACES) && (getNS($recent['id']) != $ns)) return false;
350 // check ACL
351 if ($flags & RECENTS_MEDIA_CHANGES) {
352 $recent['perms'] = auth_quickaclcheck(getNS($recent['id']) . ':*');
353 } else {
354 $recent['perms'] = auth_quickaclcheck($recent['id']);
356 if ($recent['perms'] < AUTH_READ) return false;
358 // check existence
359 if ($flags & RECENTS_SKIP_DELETED) {
360 $fn = (($flags & RECENTS_MEDIA_CHANGES) ? mediaFN($recent['id']) : wikiFN($recent['id']));
361 if (!file_exists($fn)) return false;
364 return $recent;