*/
class helper_plugin_watchcycle extends Plugin
{
public const MAINTAINERS_RAW = 0;
public const MAINTAINERS_FLAT = 1;
public const MAINTAINERS_EXPANDED = 2;
/**
* Create HTML for an icon showing the maintenance status of the provided pageid
*
* @param string $pageid the full pageid
*
* @return string span with inline svg icon and classes
*/
public function getSearchResultIconHTML($pageid)
{
/* @var \DokuWiki_Auth_Plugin $auth */
global $auth;
if ($auth === null) return '';
/* @var \helper_plugin_watchcycle $helper */
$helper = plugin_load('helper', 'watchcycle');
$watchcycle = p_get_metadata($pageid, 'plugin watchcycle');
if (!$watchcycle) {
return '';
}
$days_ago = $helper->daysAgo($watchcycle['last_maintainer_rev']);
$check_needed = false;
if ($days_ago > $watchcycle['cycle']) {
$check_needed = true;
}
$all = $this->getMaintainers($watchcycle['maintainer']);
$title = $this->getLang('maintained by') . implode(', ', array_keys($all)) . ' ';
if ($watchcycle['changes'] === -1) {
$title .= $this->getLang('never checked');
} else {
$title .= sprintf($this->getLang('last check'), $days_ago);
}
$class = ['plugin__watchcycle_searchresult_icon'];
if ($check_needed) {
$class[] = 'check_needed';
$title .= ' (' . $this->getLang('check needed') . ')';
}
$icon = '';
$icon .= inlineSVG(DOKU_PLUGIN . 'watchcycle/admin.svg');
$icon .= '';
return $icon;
}
/**
* @param $time
* @param $now
*
* @return int
*/
public function daysAgo($time, $now = false)
{
if (!$now) {
$now = time();
}
$diff = ($now - $time) / (60 * 60 * 24);
return (int)$diff;
}
/**
* Returns true if the maintainer definition matches existing users and groups
*
* @param string $def
* @return bool
*/
public function validateMaintainerString($def)
{
/* @var DokuWiki_Auth_Plugin $auth */
global $auth;
if ($auth === null) return false; // no valid auth setup
$all = explode(',', $def);
foreach ($all as $item) {
$item = trim($item);
if (strpos($item, '@') !== false) {
// check if group exists
if (empty($auth->retrieveUsers(0, 1, ['grps' => ltrim($item, '@')]))) {
return false;
}
} elseif ($auth->getUserData($item) === false) {
return false;
}
}
return true;
}
/**
* Returns a parsed representation of the maintainer string
*
* keys are the user and group names, value is either:
*
* - the user data array
* - null for groups
* - false for unknown users
*
* @param string $def maintainer definition as given in the syntax
* @return array
*/
public function getMaintainers($def)
{
/* @var DokuWiki_Auth_Plugin $auth */
global $auth;
$found = [];
if ($auth === null) return $found;
$all = explode(',', $def);
foreach ($all as $item) {
$item = trim($item);
if ($item[0] === '@') {
$found[$item] = null; // no detail info on groups
} else {
$found[$item] = $auth->getUserData($item);
}
}
return $found;
}
/**
* @param string $def maintainer definition as given in the syntax
* @return string[] list of email addresses to inform
*/
public function getMaintainerMails($def)
{
/* @var \dokuwiki\Extension\AuthPlugin $auth */
global $auth;
$auth ??= auth_setup();
if (!$auth) return [];
$data = $this->getMaintainers($def);
$mails = [];
foreach ($data as $name => $info) {
if (is_array($info)) {
$mails[] = $info['mail'];
} elseif ($name[0] === '@' && $auth->canDo('getUsers')) {
$members = $auth->retrieveUsers(0, 0, ['grps' => ltrim($name, '@')]);
foreach ($members as $user) {
$mails[] = $user['mail'];
}
}
}
return array_values(array_unique($mails));
}
/**
* @param string $user
* @param string $def
* @return bool
*/
public function isMaintainer($user, $def)
{
/* @var DokuWiki_Auth_Plugin $auth */
global $auth;
if ($auth === null) return false;
if ($user === '') return false;
$userData = $auth->getUserData($user);
$all = explode(',', $def);
foreach ($all as $item) {
$item = trim($item);
if (strpos($item, '@') !== false && in_array(ltrim($item, '@'), $userData['grps'])) {
return true;
} elseif ($item === $user) {
return true;
}
}
return false;
}
/**
* Inform all maintainers that the page needs checking
*
* @param string $def defined maintainers
* @param string $page that needs checking
*/
public function informMaintainer($def, $page)
{
$mails = $this->getMaintainerMails($def);
foreach ($mails as $mail) {
$this->sendMail($mail, $page);
}
}
/**
* Sends an email
*
* @param array $mail
* @param string $page
*/
protected function sendMail($mail, $page)
{
$mailer = new Mailer();
$mailer->to($mail);
$mailer->subject($this->getLang('mail subject'));
$text = sprintf($this->getLang('mail body'), $page);
$link = '' . $page . '';
$html = sprintf($this->getLang('mail body'), $link);
$mailer->setBody($text, null, null, $html);
if (!$mailer->send()) {
msg($this->getLang('error mail'), -1);
}
}
/**
* Puts users and groups into a flat array; useful for simple string output
* @param array $all
* @return array
*/
protected function flattenMaintainers($all)
{
if (empty($all['users'])) {
return $all;
}
$users = array_map(static fn($user) => $user['name'], $all['users']);
return array_merge($users, $all['groups']);
}
/**
* Expands groups into users; useful for email notification
*
* @param array $all
* @return array
*/
protected function expandMaintainers($all)
{
if (empty($all['groups'])) {
return $all;
}
/* @var DokuWiki_Auth_Plugin $auth */
global $auth;
if ($auth === null) return [];
$members = [];
foreach ($all['groups'] as $group) {
$members = array_merge($members, $auth->retrieveUsers(0, 0, ['grps' => ltrim($group, '@')]));
}
// merge eliminates any duplicates since we use string keys
return array_merge($all['users'], $members);
}
}