*/ class action_plugin_tos extends DokuWiki_Action_Plugin { const FORMFIELD = 'plugin__tos_accept'; /** * @inheritDoc */ public function register(Doku_Event_Handler $controller) { $controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'checkTosAccept'); $controller->register_hook('TPL_ACT_UNKNOWN', 'BEFORE', $this, 'showTos'); } /** * Check if the TOCs have been accepted and update the state if needed * * @param Doku_Event $event event object by reference * @param mixed $param * @return void */ public function checkTosAccept(Doku_Event $event, $param) { global $INPUT; global $INFO; $user = $INPUT->server->str('REMOTE_USER'); if ($user === '') return; $act = act_clean($event->data); if ($act === 'logout') return; if ($INFO['ismanager']) return; // if user accepted the TOCs right now, no further checks needed if ($INPUT->bool(self::FORMFIELD)) { $this->userTosState($user, true); $event->data = 'redirect'; return; } // ensure newest TOCs have been accepted before $newest = $this->newestTOS(); if (!$newest) return; // we don't have a valid TOS, yet $accepted = $this->userTosState($user); if ($accepted >= $newest) return; $event->data = 'plugin_tos'; } /** * Display the TOS and ask to accept * * @param Doku_Event $event event object by reference * @param mixed $param * @return void */ public function showTos(Doku_Event $event, $param) { global $ID; global $INPUT; if ($event->data !== 'plugin_tos') return; $event->preventDefault(); echo '
'; echo $this->locale_xhtml('intro'); $accepted = $this->userTosState($INPUT->server->str('REMOTE_USER')); if ($accepted) { echo ''; echo ''; echo $this->diffTos($accepted); } echo '
'; echo p_wiki_xhtml($this->getConf('tos')); echo '
'; echo ''; echo '
'; } /** * Get the most recent, non-minor revision of the TOS page * * @return int */ protected function newestTOS() { $state = $this->sessionState(); if ($state) return $state; $changes = new \dokuwiki\ChangeLog\PageChangeLog($this->getConf('tos')); if (!$changes->hasRevisions()) return 0; $start = -1; // also check current revision while ($revisions = $changes->getRevisions($start, 25)) { $start += count($revisions); foreach ($revisions as $rev) { $info = $changes->getRevisionInfo($rev); if ($info['type'] === 'E' || $info['type'] === 'C') { return $this->sessionState($rev); } } } return 0; } /** * Check and optionally update the last TOS-Acceptance * * @param string $user the user to check/update * @param bool $accept set true is the user accepted the TOS right now * @return int the last acceptance of the TOS */ protected function userTosState($user, $accept = false) { $tosfile = getCacheName($user, '.tos'); if ($accept) { io_makeFileDir($tosfile); io_saveFile($tosfile, $user); } return (int)@filemtime($tosfile); } /** * Read or write the current TOS time to the session * * @param int $set * @return int 0 when no info is available */ protected function sessionState($set = 0) { if (!$this->getConf('usesession')) return $set; if ($set) { session_start(); $_SESSION[self::FORMFIELD] = $set; session_write_close(); } if (isset($_SESSION[self::FORMFIELD])) { return $_SESSION[self::FORMFIELD]; } return 0; } /** * Create a inline diff of changes since the last accept * * @param int $lastaccept when the TOS was last accepted * @return string */ protected function diffTos($lastaccept) { $change = new \dokuwiki\ChangeLog\PageChangeLog($this->getConf('tos')); $oldrev = $change->getLastRevisionAt($lastaccept); $old = rawWiki($this->getConf('tos'), $oldrev); $new = rawWiki($this->getConf('tos')); $diff = new Diff(explode("\n", $old), explode("\n", $new)); $formatter = new InlineDiffFormatter(); $html = '
'; $html .= ''; $html .= html_insert_softbreaks($formatter->format($diff)); $html .= '
'; $html .= '
'; return $html; } }