sqlite) {
$db_helper = plugin_load('helper', 'approve_db');
$this->sqlite = $db_helper->getDB();
}
return $this->sqlite;
}
/**
* @param Doku_Event_Handler $controller
*/
public function register(Doku_Event_Handler $controller) {
$controller->register_hook('TPL_ACT_RENDER', 'AFTER', $this, 'handle_diff_accept');
$controller->register_hook('HTML_SHOWREV_OUTPUT', 'BEFORE', $this, 'handle_showrev');
$controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'handle_approve');
$controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'handle_viewer');
$controller->register_hook('TPL_ACT_RENDER', 'BEFORE', $this, 'handle_display_banner');
$controller->register_hook('COMMON_WIKIPAGE_SAVE', 'AFTER', $this, 'handle_pagesave_after');
// ensure a page revision is created when summary changes:
// $controller->register_hook('COMMON_WIKIPAGE_SAVE', 'BEFORE', $this, 'handle_pagesave_before');
// $controller->register_hook('COMMON_WIKIPAGE_SAVE', 'AFTER', $this, 'handle_pagesave_after');
}
/**
* @param $id
* @return bool
*/
protected function use_approve_here($id) {
$res = $this->sqlite()->query('SELECT page FROM page WHERE page=? AND hidden=0', $id);
if ($this->sqlite()->res2single($res)) {
return true;
}
return false;
}
/**
* @param $id
* @return bool|string
*/
protected function find_last_approved($id) {
$res = $this->sqlite()->query('SELECT rev FROM revision
WHERE page=? AND approved IS NOT NULL
ORDER BY rev DESC LIMIT 1', $id);
return $this->sqlite()->res2single($res);
}
/**
* @param Doku_Event $event
*/
public function handle_diff_accept(Doku_Event $event) {
global $INFO;
if (!$this->use_approve_here($INFO['id'])) return;
if ($event->data == 'diff' && isset($_GET['approve'])) {
$href = wl($INFO['id'], ['approve' => 'approve']);
ptln(''.$this->getLang('approve').'');
}
if ($this->getConf('ready_for_approval') && $event->data == 'diff' && isset($_GET['ready_for_approval'])) {
$href = wl($INFO['id'], ['ready_for_approval' => 'ready_for_approval']);
ptln(''.$this->getLang('approve').'');
}
}
/**
* @param Doku_Event $event
*/
public function handle_showrev(Doku_Event $event) {
global $INFO;
if (!$this->use_approve_here($INFO['id'])) return;
$last_approved_rev = $this->find_last_approved($INFO['id']);
if ($last_approved_rev == $INFO['rev']) {
$event->preventDefault();
}
}
// function can_approve() {
// global $ID;
// return auth_quickaclcheck($ID) >= AUTH_DELETE;
// }
//
// function can_edit() {
// global $ID;
// return auth_quickaclcheck($ID) >= AUTH_EDIT;
// }
/**
* @param Doku_Event $event
*/
public function handle_approve(Doku_Event $event) {
global $INFO;
if (!$this->use_approve_here($INFO['id'])) return;
if ($event->data == 'show' && isset($_GET['approve']) &&
auth_quickaclcheck($INFO['id']) >= AUTH_DELETE) {
$res = $this->sqlite()->query('SELECT MAX(version)+1 FROM revision
WHERE page=?', $INFO['id']);
$next_version = $this->sqlite()->res2single($res);
if (!$next_version) {
$next_version = 1;
}
//approved IS NULL prevents from overriding already approved page
$this->sqlite()->query('UPDATE revision
SET approved=?, version=?
WHERE page=? AND current=1 AND approved IS NULL',
date('c'), $next_version, $INFO['id']);
header('Location: ' . wl($INFO['id']));
} elseif ($event->data == 'show' && isset($_GET['ready_for_approval']) &&
auth_quickaclcheck($INFO['id']) >= AUTH_EDIT) {
$this->sqlite()->query('UPDATE revision SET ready_for_approval=?
WHERE page=? AND current=1 AND ready_for_approval IS NULL',
date('c'), $INFO['id']);
header('Location: ' . wl($INFO['id']));
}
}
/**
* Redirect to newest approved page for user that don't have EDIT permission.
*
* @param Doku_Event $event
*/
public function handle_viewer(Doku_Event $event) {
global $INFO;
if ($event->data != 'show') return;
//apply only to current page
if (!$INFO['rev']) return;
if (auth_quickaclcheck($INFO['id']) >= AUTH_EDIT) return;
if (!$this->use_approve_here($INFO['id'])) return;
$last_approved_rev = $this->find_last_approved($INFO['id']);
//no page is approved
if (!$last_approved_rev) return;
$last_change_date = @filemtime(wikiFN($INFO['id']));
//current page is approved
if ($last_approved_rev == $last_change_date) return;
header("Location: " . wl($INFO['id'], ['rev' => $last_approved_rev]));
}
// function find_lastest_approved() {
// global $ID;
// $m = p_get_metadata($ID);
// $sum = $m['last_change']['sum'];
// if ($sum == $this->getConf('sum approved'))
// return 0;
//
// $changelog = new PageChangeLog($ID);
//
// $chs = $changelog->getRevisions(0, 10000);
// foreach ($chs as $rev) {
// $ch = $changelog->getRevisionInfo($rev);
// if ($ch['sum'] == $this->getConf('sum approved'))
// return $rev;
// }
// return -1;
// }
/**
* @param Doku_Event $event
*/
public function handle_display_banner(Doku_Event $event) {
global $INFO;
if ($event->data != 'show') return;
if (!$INFO['exists']) return;
if (!$this->use_approve_here($INFO['id'])) return;
// $last_change_date = p_get_metadata($INFO['id'], 'last_change date');
$last_change_date = @filemtime(wikiFN($INFO['id']));
$rev = !$INFO['rev'] ? $last_change_date : $INFO['rev'];
$res = $this->sqlite()->query('SELECT ready_for_approval, approved, version
FROM revision
WHERE page=? AND rev=?', $INFO['id'], $rev);
$approve = $this->sqlite()->res_fetch_assoc($res);
$classes = [];
if ($this->getConf('prettyprint')) {
$classes[] = 'plugin__approve_noprint';
}
if ($approve['approved']) {
$classes[] = 'plugin__approve_green';
} elseif ($this->getConf('ready_for_approval') && $approve['ready_for_approval']) {
$classes[] = 'plugin__approve_ready';
} else {
$classes[] = 'plugin__approve_red';
}
ptln('
');
tpl_pageinfo();
ptln(' | ');
if ($approve['approved']) {
ptln('
'.$this->getLang('approved').' ('
. $this->getLang('version') . ': ' . $approve['version'] . ')');
//not the newest page
if ($rev != $last_change_date) {
$res = $this->sqlite()->query('SELECT rev, current FROM revision
WHERE page=? AND approved IS NOT NULL
ORDER BY rev DESC LIMIT 1', $INFO['id']);
$lastest_approve = $this->sqlite()->res_fetch_assoc($res);
//we can see drafts
if (auth_quickaclcheck($INFO['id']) >= AUTH_EDIT) {
ptln('
');
ptln($this->getLang($lastest_approve['current'] ? 'newest_approved' : 'newest_draft'));
ptln('');
} else {
$urlParameters = [];
if (!$lastest_approve['current']) {
$urlParameters['rev'] = $lastest_approve['rev'];
}
ptln('
');
ptln($this->getLang('newest_approved'));
ptln('');
}
}
} else {
ptln('
'.$this->getLang('draft').'');
if ($this->getConf('ready_for_approval') && $approve['ready_for_approval']) {
ptln('
| '.$this->getLang('marked_approve_ready').'');
}
$res = $this->sqlite()->query('SELECT rev, current FROM revision
WHERE page=? AND approved IS NOT NULL
ORDER BY rev DESC LIMIT 1', $INFO['id']);
$lastest_approve = $this->sqlite()->res_fetch_assoc($res);
//not exists approve for current page
if (!$lastest_approve) {
//not the newest page
if ($rev != $last_change_date) {
ptln('
');
ptln($this->getLang('newest_draft'));
ptln('');
}
} else {
$urlParameters = [];
if (!$lastest_approve['current']) {
$urlParameters['rev'] = $lastest_approve['rev'];
}
ptln('
');
ptln($this->getLang('newest_approved'));
ptln('');
}
//we are in current page
if ($rev == $last_change_date) {
$last_approved_rev = 0;
if (isset($lastest_approve['rev'])) {
$last_approved_rev = $lastest_approve['rev'];
}
if ($this->getConf('ready_for_approval') &&
auth_quickaclcheck($INFO['id']) >= AUTH_EDIT &&
!$approve['ready_for_approval']) {
$urlParameters = [
'rev' => $last_approved_rev,
'do' => 'diff',
'ready_for_approval' => 'ready_for_approval'
];
ptln(' |
');
ptln($this->getLang('approve_ready'));
ptln('');
}
if (auth_quickaclcheck($INFO['id']) >= AUTH_DELETE) {
$urlParameters = [
'rev' => $last_approved_rev,
'do' => 'diff',
'approve' => 'approve'
];
ptln(' |
');
ptln($this->getLang('approve'));
ptln('');
}
}
}
ptln('
');
}
/**
* @return bool|string
*/
protected function prev_rev($id) {
$res = $this->sqlite()->query('SELECT rev FROM revision
WHERE page=?
AND current=1
AND approved IS NULL
AND ready_for_approval IS NULL', $id);
return $this->sqlite()->res2single($res);
}
/**
*
* @param Doku_Event $event event object by reference
* @return void
*/
public function handle_pagesave_after(Doku_Event $event) {
//no content was mde
if (!$event->data['contentChanged']) return;
$changeType = $event->data['changeType'];
if ($changeType == DOKU_CHANGE_TYPE_REVERT) {
if ($event->data['oldContent'] == '') {
$changeType = DOKU_CHANGE_TYPE_CREATE;
} else {
$changeType = DOKU_CHANGE_TYPE_EDIT;
}
}
$id = $event->data['id'];
//TODO: if created, if deleted
switch ($changeType) {
case DOKU_CHANGE_TYPE_EDIT:
case DOKU_CHANGE_TYPE_REVERT:
case DOKU_CHANGE_TYPE_MINOR_EDIT:
$last_change_date = $event->data['newRevision'];
//if the current page has approved or ready_for_approval -- keep it
$prev_rev = $this->prev_rev($id);
if ($prev_rev) {
$this->sqlite()->query('UPDATE revision SET rev=? WHERE page=? AND rev=?',
$last_change_date, $id, $prev_rev);
} else {
//keep previous record
$this->sqlite()->query('UPDATE revision SET current=0
WHERE page=?
AND current=1', $id);
$this->sqlite()->storeEntry('revision', [
'page' => $id,
'rev' => $last_change_date,
'current' => 1
]);
}
break;
case DOKU_CHANGE_TYPE_DELETE:
//delete information about availability of a page but keep the history
$this->sqlite()->query('DELETE FROM page WHERE page=?', $id);
//delete revision if no information about approvals
$prev_rev = $this->prev_rev($id);
if ($prev_rev) {
$this->sqlite()->query('DELETE FROM revision WHERE page=? AND rev=?',
$id, $prev_rev);
} else {
$this->sqlite()->query('UPDATE revision SET current=0 WHERE page=? AND rev=?',
$id, $prev_rev);
}
break;
case DOKU_CHANGE_TYPE_CREATE:
$last_change_date = $event->data['newRevision'];
//TODO should be checked against no_approve_rev
$this->sqlite()->storeEntry('page', [
'page' => $id
]);
$this->sqlite()->storeEntry('revision', [
'page' => $id,
'rev' => $last_change_date,
'current' => 1
]);
break;
}
}
/**
* Check if the page has to be changed
*
* @param Doku_Event $event event object by reference
* @param mixed $param [the parameters passed as fifth argument to register_hook() when this
* handler was registered]
* @return void
*/
// public function handle_pagesave_before(Doku_Event $event, $param) {
// global $REV;
// $id = $event->data['id'];
// if (!$this->hlp->use_approve_here($id)) return;
//
// //save page if summary is provided
// if($event->data['summary'] == $this->getConf('sum approved') ||
// $event->data['summary'] == $this->getConf('sum ready for approval')) {
// $event->data['contentChanged'] = true;
// }
// }
/**
* @param Doku_Event $event
* @param $param
*/
// public function handle_pagesave_after(Doku_Event $event, $param) {
// global $REV;
// $id = $event->data['id'];
// if (!$this->hlp->use_approve_here($id)) return;
//
// //save page if summary is provided
// if($event->data['summary'] == $this->getConf('sum approved')) {
//
// $versions = p_get_metadata($id, ApproveConst::METADATA_VERSIONS_KEY);
// //calculate versions
// if (!$versions) {
// $this->render_metadata_for_approved_page($id, $event->data['newRevision']);
// } else {
// $curver = $versions[0] + 1;
// $versions[0] = $curver;
// $versions[$event->data['newRevision']] = $curver;
// p_set_metadata($id, array(ApproveConst::METADATA_VERSIONS_KEY => $versions));
// }
// }
// }
/**
* Calculate current version
*
* @param $id
* @return array
*/
// protected function render_metadata_for_approved_page($id, $currev=false) {
// if (!$currev) $currev = @filemtime(wikiFN($id));
//
// $version = $this->approved($id);
// //version for current page
// $curver = $version + 1;
// $versions = array(0 => $curver, $currev => $curver);
//
// $changelog = new PageChangeLog($id);
// $first = 0;
// $num = 100;
// while (count($revs = $changelog->getRevisions($first, $num)) > 0) {
// foreach ($revs as $rev) {
// $revInfo = $changelog->getRevisionInfo($rev);
// if ($revInfo['sum'] == $this->getConf('sum approved')) {
// $versions[$rev] = $version;
// $version -= 1;
// }
// }
// $first += $num;
// }
//
// p_set_metadata($id, array(ApproveConst::METADATA_VERSIONS_KEY => $versions));
//
// return $versions;
// }
/**
* Get the number of approved pages
* @param $id
* @return int
*/
// protected function approved($id) {
// $count = 0;
//
// $changelog = new PageChangeLog($id);
// $first = 0;
// $num = 100;
// while (count($revs = $changelog->getRevisions($first, $num)) > 0) {
// foreach ($revs as $rev) {
// $revInfo = $changelog->getRevisionInfo($rev);
// if ($revInfo['sum'] == $this->getConf('sum approved')) {
// $count += 1;
// }
// }
// $first += $num;
// }
//
// return $count;
// }
}