1<?php
2// (c) Copyright by authors of the Tiki Wiki CMS Groupware Project
3//
4// All Rights Reserved. See copyright.txt for details and a complete list of authors.
5// Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See license.txt for details.
6// $Id$
7
8$section = 'wiki page';
9$section_class = "tiki_wiki_page manage";	// This will be body class instead of $section
10require_once('tiki-setup.php');
11$histlib = TikiLib::lib('hist');
12require_once('lib/wiki/renderlib.php');
13
14$access->check_feature('feature_wiki');
15
16if (! isset($_REQUEST["source"])) {
17	$access->check_feature('feature_history');
18} else {
19	$access->check_feature('feature_source');
20}
21// Get the page from the request var or default it to HomePage
22if (! isset($_REQUEST["page"])) {
23	$smarty->assign('msg', tra("No page indicated"));
24	$smarty->display("error.tpl");
25	die;
26} else {
27	$page = $_REQUEST["page"];
28	$smarty->assign_by_ref('page', $_REQUEST["page"]);
29}
30
31$auto_query_args = ['page', 'oldver', 'newver', 'diff_style', 'paginate', 'history_offset'];
32
33// Now check permissions to access this page
34if (! isset($_REQUEST["source"])) {
35	$access->check_permission('tiki_p_wiki_view_history', '', 'wiki page', $_REQUEST['page']);
36} else {
37	$access->check_permission('tiki_p_wiki_view_source', '', 'wiki page', $_REQUEST['page']);
38}
39$info = $tikilib->get_page_info($page);
40if (empty($info)) {
41	$smarty->assign('msg', tra('No page indicated'));
42	$smarty->display('error.tpl');
43	die;
44}
45
46$tikilib->get_perm_object($_REQUEST['page'], 'wiki page', $info);
47
48if (isset($_REQUEST['preview'], $_REQUEST['flaggedrev'], $_REQUEST['page']) && $prefs['flaggedrev_approval'] == 'y' && $tiki_p_wiki_approve == 'y') {
49	$targetFlag = null;
50
51	if (isset($_REQUEST['approve'])) {
52		$targetFlag = 'OK';
53		$targetVersion = (int) $_REQUEST['approve'];
54	} elseif (isset($_REQUEST['unapprove'])) {
55		$targetFlag = 'REJECT';
56		$targetVersion = (int) $_REQUEST['unapprove'];
57	}
58
59	if ($targetFlag) {
60		$flaggedrevisionlib = TikiLib::lib('flaggedrevision');
61
62		$flaggedrevisionlib->flag_revision($info['pageName'], $targetVersion, 'moderation', $targetFlag);
63	}
64}
65
66$smarty->assign_by_ref('info', $info);
67
68if ($prefs['feature_contribution'] == 'y') {
69	$contributionlib = TikiLib::lib('contribution');
70	$contributions = $contributionlib->get_assigned_contributions($page, 'wiki page');
71	$smarty->assign_by_ref('contributions', $contributions);
72	if ($prefs['feature_contributor_wiki'] == 'y') {
73		$contributors = $logslib->get_wiki_contributors($info);
74		$smarty->assign_by_ref('contributors', $contributors);
75	}
76}
77
78$paginate = (isset($_REQUEST['paginate']) && $_REQUEST['paginate'] == 'on') || ! isset($_REQUEST['diff_style']);
79$smarty->assign('paginate', $paginate);
80
81if (isset($_REQUEST['history_offset']) && $paginate) {
82	$history_offset = (int) $_REQUEST['history_offset'];
83} else {
84	$history_offset = 0;
85}
86$smarty->assign('history_offset', $history_offset);
87
88if (isset($_REQUEST['history_pagesize']) && $paginate) {
89	$history_pagesize = (int) $_REQUEST['history_pagesize'];
90} elseif (isset($_SESSION['history_pagesize'])) {
91	$history_pagesize = (int) $_SESSION['history_pagesize'];
92} else {
93	$history_pagesize = (int) $prefs['maxRecords'];
94}
95$_SESSION['history_pagesize'] = $history_pagesize;
96$smarty->assign('history_pagesize', $history_pagesize);
97
98// fetch page history, but omit the actual page content (to save memory)
99$history = $histlib->get_page_history($page, false, $history_offset, $paginate ? $history_pagesize : -1);
100$smarty->assign('history_cant', $histlib->get_nb_history($page) - 1);
101
102if ($prefs['flaggedrev_approval'] == 'y') {
103	$flaggedrevisionlib = TikiLib::lib('flaggedrevision');
104
105	if ($flaggedrevisionlib->page_requires_approval($page)) {
106		$approved_versions = $flaggedrevisionlib->get_versions_with($page, 'moderation', 'OK');
107		$rejected_versions = $flaggedrevisionlib->get_versions_with($page, 'moderation', 'REJECT');
108
109		$smarty->assign('flaggedrev_approval', true);
110
111		$info['approved'] = in_array($info['version'], $approved_versions);
112		$info['rejected'] = in_array($info['version'], $rejected_versions);
113
114		$new_history = [];
115
116		foreach ($history as $version) {
117			$version['approved'] = in_array($version['version'], $approved_versions);
118			$version['rejected'] = in_array($version['version'], $rejected_versions);
119			if ($version['rejected']) {
120				$version['rejection_reason'] = $flaggedrevisionlib->get_flag_comment($page, $version['version'], 'moderation', 'REJECT');
121			}
122			if ($tiki_p_wiki_view_latest == 'y' || $version['approved'] || $version['rejected']) {
123				$new_history[] = $version;
124			}
125		}
126
127		while ($tiki_p_wiki_approve != 'y' && sizeof($new_history) > 0 && ! $new_history[0]['approved'] && ! $new_history[0]['rejected']) {
128			array_shift($new_history);
129		}
130
131		$history = $new_history;
132	}
133}
134
135if (! isset($_REQUEST['show_all_versions'])) {
136	$_SESSION['show_all_versions'] = isset($_SESSION['show_all_versions']) ? $_SESSION['show_all_versions'] : 'y';
137} else {
138	$_SESSION['show_all_versions'] = $_REQUEST['show_all_versions'] === 'n' ? 'n' : 'y';
139}
140
141$sessions = [];
142if (count($history) > 0) {
143	$lastuser = '';		// calculate edit session info
144	$lasttime = 0;		// secs
145	$idletime = 1800; 	// max gap between edits in sessions 30 mins? Maybe should use a pref?
146	for ($i = 0, $cnt = count($history); $i < $cnt; $i++) {
147		if ((isset($history[$i]['user']) && $history[$i]['user'] != $lastuser) || (isset($history[$i]['lastModif']) && $lasttime - $history[$i]['lastModif'] > $idletime)) {
148			$sessions[] = $history[$i];
149			//$history[$i]['session'] = $history[$i]['version'];
150		} elseif (count($sessions) > 0) {
151			$history[$i]['session'] = $sessions[count($sessions) - 1]['version'];
152		}
153		if (isset($history[$i]['user'])) {
154			$lastuser = $history[$i]['user'];
155		} else {
156			$lastuser = '';
157		}
158		if (isset($history[$i]['lastModif'])) {
159			$lasttime = $history[$i]['lastModif'];
160		} else {
161			$lasttime = 0;
162		}
163	}
164	$csesh = count($sessions) + 1;
165	foreach ($history as &$h) {	// move ending 'version' into starting 'session'
166		if (! empty($h['session'])) {
167			foreach ($history as &$h2) {
168				if ($h2['version'] == $h['session']) {
169					$h2['session'] = $h['version'];
170				}
171			}
172			$h['session'] = '';
173		}
174	}
175	if ($_SESSION['show_all_versions'] == "n") {
176		for ($i = 0, $cnt = count($history); $i < $cnt; $i++) {	// remove versions inside sessions
177			if (! empty($history[$i]['session']) && $i < $cnt - 1) {
178				$seshend = $history[$i]['session'];
179				$i++;
180				for ($i; $i < $cnt; $i++) {
181					if ($history[$i]['version'] >= $seshend) {
182						unset($history[$i]);
183					} else {
184						$i--;
185						break;
186					}
187				}
188			}
189		}
190	}
191}
192$smarty->assign('show_all_versions', $_SESSION['show_all_versions']);
193$history_versions = [];
194$history_sessions = [];
195reset($history);
196foreach ($history as &$h) {	// as $h has been used by reference before it needs to be so again (it seems)
197	$history_versions[] = (int)$h['version'];
198	$history_sessions[] = isset($h['session']) ? (int)$h['session'] : 0;
199}
200$history_versions = array_reverse($history_versions);
201$history_sessions = array_reverse($history_sessions);
202$history_versions[] = (int) $info['version'];	// current is last one
203$history_sessions[] = 0;
204$smarty->assign_by_ref('history', $history);
205
206// for pagination
207$smarty->assign('ver_cant', count($history_versions));
208
209if (isset($_REQUEST['clear_versions'])) {
210	unset($_REQUEST['clear_versions']);
211	unset($_REQUEST['newver']);
212	unset($_REQUEST['newver_idx']);
213	unset($_REQUEST['oldver']);
214	unset($_REQUEST['oldver_idx']);
215	unset($_REQUEST['compare']);
216	unset($_REQUEST['diff_style']);
217}
218// calculate version and offset
219if (isset($_REQUEST['bothver_idx'])) {
220	if ($_REQUEST['bothver_idx'] == 0) {
221		$_REQUEST['bothver_idx'] = 1;
222	}
223	$_REQUEST['oldver_idx'] = $_REQUEST['bothver_idx'] - 1;
224	$_REQUEST['newver_idx'] = $_REQUEST['bothver_idx'];
225	if ($_SESSION['show_all_versions'] == 'n' && ! empty($history_sessions[$_REQUEST['bothver_idx']])) {
226		$_REQUEST['oldver_idx'] = $_REQUEST['bothver_idx'];
227	}
228}
229if (isset($_REQUEST['newver_idx'])) {
230	$newver = $history_versions[$_REQUEST['newver_idx']];
231} else {
232	if (isset($_REQUEST['newver']) && $_REQUEST['newver'] > 0) {
233		$newver = (int)$_REQUEST["newver"];
234		if (in_array($newver, $history_versions)) {
235			$_REQUEST['newver_idx'] = array_search($newver, $history_versions);
236		} else {
237			$_REQUEST['newver_idx'] = array_search($newver, $history_sessions);
238		}
239	} else {
240		$newver = $history_versions[count($history_versions) - 1];
241		$_REQUEST['newver_idx'] = count($history_versions) - 1;
242	}
243}
244if (isset($_REQUEST['oldver_idx'])) {
245	$oldver = $history_versions[$_REQUEST['oldver_idx']];
246	if ($_SESSION['show_all_versions'] == 'n' && ! empty($history_sessions[$_REQUEST['oldver_idx']])) {
247		$oldver = $history_sessions[$_REQUEST['oldver_idx']];
248	}
249} else {
250	if (isset($_REQUEST['oldver']) && $_REQUEST['oldver'] > 0) {
251		$oldver = (int)$_REQUEST["oldver"];
252		if (in_array($oldver, $history_versions)) {
253			$_REQUEST['oldver_idx'] = array_search($oldver, $history_versions);
254		} else {
255			$_REQUEST['oldver_idx'] = array_search($oldver, $history_sessions);
256		}
257	} else {
258		$oldver = $history_versions[count($history_versions) - 1];
259		$_REQUEST['oldver_idx'] = count($history_versions) - 1;
260	}
261}
262if ($_REQUEST['oldver_idx'] + 1 == $_REQUEST['newver_idx']) {
263	$_REQUEST['bothver_idx'] = $_REQUEST['newver_idx'];
264}
265$_REQUEST['oldver'] = $oldver;
266$_REQUEST['newver'] = $newver;
267
268// source view
269if (isset($_REQUEST['source_idx'])) {
270	$source = $history_versions[$_REQUEST['source_idx']];
271} else {
272	if (isset($_REQUEST['source'])) {
273		$source = (int)$_REQUEST["source"];
274		if ($source > 0) {
275			$_REQUEST['source_idx'] = array_search($source, $history_versions);
276		} else {
277			$_REQUEST['source_idx'] = count($history_versions) - 1;
278			$smarty->assign('noHistory', true);
279		}
280	}
281}
282if (isset($_REQUEST['preview_idx'])) {
283	$preview = $history_versions[$_REQUEST['preview_idx']];
284} else {
285	if (isset($_REQUEST['preview_date'])) {
286		$_REQUEST['preview'] = (int)$histlib->get_version_by_time($page, $_REQUEST["preview_date"]);
287	}
288
289	if (isset($_REQUEST['preview'])) {
290		$preview = (int)$_REQUEST["preview"];
291		if ($_REQUEST['preview'] > 0) {
292			$_REQUEST['preview_idx'] = array_search($preview, $history_versions);
293		} else {
294			$_REQUEST['preview_idx'] = count($history_versions) - 1;
295			$smarty->assign('noHistory', true);
296		}
297	}
298}
299
300if (isset($_REQUEST['version'])) {
301	$rversion = $_REQUEST['version'];
302}
303
304$smarty->assign('source', false);
305if (isset($source)) {
306	if ($source == '' && isset($rversion)) {
307		$source = $rversion;
308	}
309	if ($source == $info["version"] || $source == 0) {
310		$smarty->assign('sourced', $info["data"]);
311		$smarty->assign('source', $info['version']);
312	} else {
313		$version = $histlib->get_version($page, $source);
314		if ($version) {
315			$smarty->assign('sourced', $version["data"]);
316			$smarty->assign('source', $source);
317		}
318	}
319}
320$smarty->assign('preview', false);
321if (isset($preview)) {
322	if ($preview == '' && isset($rversion)) {
323		$preview = $rversion;
324	}
325	if ($preview == $info['version'] || $preview == 0) {
326		if ($prefs['flaggedrev_approval'] != 'y' || ! $flaggedrevisionlib->page_requires_approval($page) || $info['approved'] || $info['rejected'] || $tiki_p_wiki_approve == 'y') {
327			$previewd = (new WikiLibOutput($info, $info['data'], ['preview_mode' => true, 'is_html' => $info['is_html']]))->parsedValue;
328			$smarty->assign('previewd', $previewd);
329		}
330		$smarty->assign('preview', $info['version']);
331	} else {
332		$version = $histlib->get_version($page, $preview);
333		if ($version) {
334			$previewd = (new WikiLibOutput($version, $version['data'], ['preview_mode' => true, 'is_html' => $version['is_html']]))->parsedValue;
335			$smarty->assign('previewd', $previewd);
336			$smarty->assign('preview', $preview);
337		}
338	}
339
340	$smarty->assign('flaggedrev_preview_approved', isset($approved_versions) && in_array($preview, $approved_versions));
341	$smarty->assign('flaggedrev_preview_rejected', isset($rejected_versions) && in_array($preview, $rejected_versions));
342}
343if (isset($preview)) {
344	$smarty->assign('current', $preview);
345} elseif (isset($source)) {
346	$smarty->assign('current', $source);
347} elseif ($newver) {
348	$smarty->assign('current', $newver);
349} elseif ($oldver) {
350	$smarty->assign('current', $oldver);
351} else {
352	$smarty->assign('current', 0);
353}
354if ($prefs['feature_multilingual'] == 'y' && isset($_REQUEST['show_translation_history'])) {
355	$multilinguallib = TikiLib::lib('multilingual');
356	$smarty->assign('show_translation_history', 1);
357	$sources = $multilinguallib->getSourceHistory($info['page_id']);
358	$targets = $multilinguallib->getTargetHistory($info['page_id']);
359} else {
360	$sources = [];
361	$targets = [];
362}
363$smarty->assign_by_ref('translation_sources', $sources);
364$smarty->assign_by_ref('translation_targets', $targets);
365if (isset($_REQUEST["diff2"])) { // previous compatibility
366	if ($_REQUEST["diff2"] == '' && isset($rversion)) {
367		$_REQUEST["diff2"] = $rversion;
368	}
369	$_REQUEST["compare"] = "y";
370	$oldver = (int)$_REQUEST["diff2"];
371}
372if (! isset($newver)) {
373	$newver = 0;
374}
375if ($prefs['feature_multilingual'] == 'y') {
376	$multilinguallib = TikiLib::lib('multilingual');
377	$langLib = TikiLib::lib('language');
378	$languages = $langLib->list_languages();
379	$smarty->assign_by_ref('languages', $languages);
380	if (isset($_REQUEST["update_translation"])) {
381		// Update translation button clicked. Forward request to edit page of translation.
382		if (isset($_REQUEST['tra_lang'])) {
383			$target = $_REQUEST['tra_lang'];
384		} else {
385			die('Invalid call to this page. Specify tra_lang');
386		}
387		// Find appropriate translation page
388		$langs = $multilinguallib->getTranslations('wiki page', $info['page_id'], $info['pageName'], true);
389		$pageName = '';
390		foreach ($langs as $pageInfo) {
391			if ($target == (string)$pageInfo['lang']) {
392				$pageName = $pageInfo['objName'];
393			}
394		}
395		// Build URI / Redirect
396		$diff_style = isset($_REQUEST['diff_style']) ? rawurlencode($_REQUEST['diff_style']) : rawurlencode($info['is_html'] === '1' ? 'htmldiff' : $prefs['default_wiki_diff_style']);
397		$comment = rawurlencode("Updating from $page at version {$info['version']}");
398		if ($newver == 0) {
399			$newver = $info['version'];
400		}
401		if ($pageName) {
402			$uri = "tiki-editpage.php?page=$pageName&source_page=$page&diff_style=$diff_style&oldver=$oldver&newver=$newver&comment=$comment";
403		} else {
404			$uri = "tiki-edit_translation.php?page=$page";
405		}
406		header("Location: $uri");
407		exit;
408	}
409}
410$current_version = $info["version"];
411$comparing = isset($_GET['newver']) || isset($_GET['oldver']);
412$not_comparing = $comparing ? 'false' : 'true';
413
414$headerlib->add_jq_onready(
415<<<JS
416\$("input[name=oldver], input[name=newver]").change(function () {
417	var ver = parseInt(\$(this).val(), 10), ver2;
418	if (ver == 0) { ver = $current_version; }
419	if (\$(this).attr("name") == "oldver") {
420		\$("input[name=newver]").each(function () {
421			ver2 = parseInt(\$(this).val(), 10);
422			if (ver2 == 0) { ver2 = $current_version; }
423			\$(this).attr("disabled", (ver2 <= ver));
424		});
425	} else if (\$(this).attr("name") == "newver") {
426		\$("input[name=oldver]").each(function () {
427			ver2 = parseInt(\$(this).val(), 10);
428			if (ver2 == 0) { ver2 = $current_version; }
429			\$(this).attr("disabled", (ver2 >= ver));
430		});
431	}
432});
433if (\$("input[name=newver][checked=checked]").length) {
434	\$("input[name=newver][checked=checked]").change();
435	\$("input[name=oldver][checked=checked]").change();
436} else if ($not_comparing) {
437	\$("input[name=newver]:eq(0)").prop("checked", "checked").change();
438	\$("input[name=oldver]:eq(1)").prop("checked", "checked").change();
439}
440JS
441);
442if ($comparing) {
443	histlib_helper_setup_diff($page, $oldver, $newver, (! empty($_REQUEST['diff_style']) ? $_REQUEST['diff_style'] : ''));
444
445	if (isset($approved_versions)) {
446		$smarty->assign('flaggedrev_compare_approve', ! in_array($newver, $approved_versions));
447	}
448} else {
449	$smarty->assign('diff_style', $info['is_html'] === '1' ? 'htmldiff' : $prefs['default_wiki_diff_style']);
450}
451
452if ($info["flag"] == 'L') {
453	$smarty->assign('lock', true);
454} else {
455	$smarty->assign('lock', false);
456}
457
458if (isset($_REQUEST['nohistory'])) {
459	$smarty->assign('noHistory', true);
460}
461
462$smarty->assign('editable', TikiLib::lib('wiki')->is_editable($page, $user, $info));
463
464TikiLib::events()->trigger(
465	'tiki.wiki.view',
466	array_merge(
467		[
468			'type' => 'wiki page',
469			'object' => $page,
470			'user' => $GLOBALS['user'],
471		],
472		$info
473	)
474);
475
476// disallow robots to index page:
477$smarty->assign('page_user', $info['user']);
478$smarty->assign('metatag_robots', 'NOINDEX, NOFOLLOW');
479
480include_once('tiki-section_options.php');
481if ($prefs['feature_theme_control'] == 'y') {
482	$cat_type = 'wiki page';
483	$cat_objid = $_REQUEST['page'];
484	include('tiki-tc.php');
485}
486// Display the template
487$smarty->assign('mid', 'tiki-pagehistory.tpl');
488$smarty->display("tiki.tpl");
489