<?php if (!defined('PmWiki')) exit(); /** Pending Changes extension for PmWiki Periodically fetches the current page revision number and adds a message to the page and to the document.title. Written by (c) Petko Yotov 2019-2020 www.pmwiki.org/petko This text is written for PmWiki; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. See pmwiki.php for full details and lack of warranty. */ # Version date $RecipeInfo['PendingChanges']['Version'] = '20201220'; SDVA($HandleActions, array('pending'=> 'HandlePendingChanges')); SDVA($HandleAuth, array('pending' => 'read')); SDVA($HTMLStylesFmt, array('PendingChanges'=>'#pendingchanges {background-color: #ff8; cursor: pointer;}')); XLSDV('en',array( 'PendingChanges' => '(%s) Pending changes, click to reload.', 'EnableDesktopNotifications' => 'Enable desktop notifications', )); Markup('PendingChanges', '>include', '/\\(:pendingchanges( .+?)?:\\)/', 'FmtPendingChanges'); SDVA($PendingChanges, array( 'delayminutes' => 5, 'querySelector' => '#wikitext', 'where' => 'afterbegin', 'page-override' => array('Site.AllRecentChangesShort' => 'Site.AllRecentChanges'), 'script' => ' <script> var PendingChangesVars = %s; PendingChangesVars.prev = PendingChangesVars.rev; function zpad(n) { if(n<10) return "0" +n; return n; } function CheckPendingChanges() { var xhr; if (window.XMLHttpRequest) xhr = new XMLHttpRequest(); else if (window.ActiveXObject) xhr = new ActiveXObject("Microsoft.XMLHTTP"); else return false; var ltreload = document.querySelector("small.ltreload"); ltreload.innerHTML += "..."; xhr.open("GET", PendingChangesVars.url, true); xhr.send(""); xhr.onreadystatechange = function() { if(xhr.readyState != 4) return; var rt = xhr.responseText; if(xhr.status != 200 || rt.indexOf("ERROR")>=0 || rt == "") { return; } var rev = parseInt(rt); if(isNaN(rev)) return; if(ltreload) { var now = new Date(); var h = zpad(now.getHours()), m = zpad(now.getMinutes()); ltreload.innerHTML = h + ":" + m; } if(rev == PendingChangesVars.prev) { return; } PendingChangesVars.prev = rev; var el = document.querySelector("#pendingchanges var"); if(!el) { PendingChangesVars.parentNode.insertAdjacentHTML(PendingChangesVars.where, "<div id=\'pendingchanges\'>"+PendingChangesVars.text+"</div>" ); el = document.querySelector("#pendingchanges var"); if(!el) return clearInterval(PendingChanges.interval); document.getElementById("pendingchanges").addEventListener("click", function(){self.location.reload(true);}); } var count = rev - PendingChangesVars.rev; el.innerHTML = count; document.title = "("+count+") " + document.title.replace(/^\\s*\\(\\d+\\)\\s*/,""); if (Notification.permission === "granted") var n = new Notification(document.title, {body: document.querySelector("#pendingchanges").textContent}); }; } document.addEventListener("DOMContentLoaded", function(){ var parent = document.querySelector(PendingChangesVars.querySelector); if(!parent) return; PendingChangesVars.parentNode = parent; PendingChangesVars.interval = setInterval(CheckPendingChanges, PendingChangesVars.delayminutes*1000*60); if(! window.Notification) window.Notification = {permission:"denied"}; if (Notification.permission === "default") { parent.insertAdjacentHTML(PendingChangesVars.where, " <button id=\'pc_notif\'>"+PendingChangesVars.enable+"</button>"); document.getElementById("pc_notif").addEventListener("click", function(){ Notification.requestPermission(); this.parentNode.removeChild(this); }); } }); </script> ', )); function FmtPendingChanges($m) { global $HTMLHeaderFmt, $PendingChanges, $PCache; extract($GLOBALS['MarkupToHTML']); $pn = IsEnabled($PendingChanges['page-override'][$pagename], $pagename); if(! isset($PCache[$pn]['rev'])) { $page = RetrieveAuthPage($pn, 'read', false, READPAGE_CURRENT); PCache($pn, $page); } $out = array( 'rev' => $PCache[$pn]['rev'], 'text' => sprintf(XL('PendingChanges'), '<var></var>'), 'enable' => XL('EnableDesktopNotifications'), 'delayminutes' => $PendingChanges['delayminutes'], 'querySelector' => $PendingChanges['querySelector'], 'where' => $PendingChanges['where'], 'url' => FmtPageName('{$PageUrl}?action=pending', $pagename) ); $script = sprintf($PendingChanges['script'], json_encode($out)); SDVA($HTMLHeaderFmt, array('PendingChanges'=>$script)); return ''; } function HandlePendingChanges($pagename, $auth='read') { global $PendingChanges; $pn = IsEnabled($PendingChanges['page-override'][$pagename], $pagename); $page = RetrieveAuthPage($pn, $auth, false, READPAGE_CURRENT); header('Content-Type: text/plain'); echo intval(@$page['rev']); exit; }