diff --git a/action/notification.php b/action/notification.php index d6aa520..59674f4 100644 --- a/action/notification.php +++ b/action/notification.php @@ -1,4 +1,5 @@ */ -// must be run within Dokuwiki +use dokuwiki\Extension\ActionPlugin; +use dokuwiki\Extension\EventHandler; +use dokuwiki\Extension\Event; +use dokuwiki\plugin\structgroup\types\Group; use dokuwiki\plugin\struct\meta\Search; use dokuwiki\plugin\struct\meta\Value; -if (!defined('DOKU_INC')) { - die(); -} - -class action_plugin_structnotification_notification extends DokuWiki_Action_Plugin +class action_plugin_structnotification_notification extends ActionPlugin { - /** * Registers a callback function for a given event * - * @param Doku_Event_Handler $controller DokuWiki's event controller object + * @param EventHandler $controller DokuWiki's event controller object * * @return void */ - public function register(Doku_Event_Handler $controller) + public function register(EventHandler $controller) { - $controller->register_hook('PLUGIN_NOTIFICATION_REGISTER_SOURCE', 'AFTER', $this, 'add_notifications_source'); - $controller->register_hook('PLUGIN_NOTIFICATION_GATHER', 'AFTER', $this, 'add_notifications'); - $controller->register_hook('PLUGIN_NOTIFICATION_CACHE_DEPENDENCIES', 'AFTER', $this, 'add_notification_cache_dependencies'); - - + $controller->register_hook('PLUGIN_NOTIFICATION_REGISTER_SOURCE', 'AFTER', $this, 'addNotificationsSource'); + $controller->register_hook('PLUGIN_NOTIFICATION_GATHER', 'AFTER', $this, 'addNotifications'); + $controller->register_hook( + 'PLUGIN_NOTIFICATION_CACHE_DEPENDENCIES', + 'AFTER', + $this, + 'addNotificationCacheDependencies' + ); } - public function add_notifications_source(Doku_Event $event) + public function addNotificationsSource(Event $event) { $event->data[] = 'structnotification'; } - public function add_notification_cache_dependencies(Doku_Event $event) + public function addNotificationCacheDependencies(Event $event) { if (!in_array('structnotification', $event->data['plugins'])) return; @@ -66,8 +68,7 @@ protected function getValueByLabel($values, $label) throw new Exception("column: $label not found in values"); } - - public function add_notifications(Doku_Event $event) + public function addNotifications(Event $event) { if (!in_array('structnotification', $event->data['plugins'])) return; @@ -92,10 +93,11 @@ public function add_notifications(Doku_Event $event) $field = $predicate['field']; $operator = $predicate['operator']; $value = $predicate['value']; + $filters = $predicate['filters']; $users_and_groups = $predicate['users_and_groups']; $message = $predicate['message']; - try { + try { $search = new Search(); foreach (explode(',', $schema) as $table) { $search->addSchema($table); @@ -106,25 +108,31 @@ public function add_notifications(Doku_Event $event) foreach ($special_columns as $special_column) { $search->addColumn($special_column); } + $this->addFiltersToSearch($search, $filters); $result = $search->execute(); $result_pids = $search->getPids(); + /* @var Value[] $row */ + $counter = count($result); /* @var Value[] $row */ - for ($i=0; $iusers_set($users_and_groups, $values); + $users_set = $this->usersSet($users_and_groups, $values); if (!isset($users_set[$user])) continue; $rawDate = $this->getValueByLabel($values, $field); if ($this->predicateTrue($rawDate, $operator, $value)) { $message_with_replacements = $this->replacePlaceholders($message, $values); - $message_with_replacements_html = p_render('xhtml', - p_get_instructions($message_with_replacements), $info); + $message_with_replacements_html = p_render( + 'xhtml', + p_get_instructions($message_with_replacements), + $info + ); $event->data['notifications'][] = [ 'plugin' => 'structnotification', - 'id' => $predicate['id'] . ':'. $schema . ':' . $pid . ':' . $rawDate, + 'id' => $predicate['id'] . ':' . $schema . ':' . $pid . ':' . $rawDate, 'full' => $message_with_replacements_html, 'brief' => $message_with_replacements_html, 'timestamp' => (int) strtotime($rawDate) @@ -141,15 +149,21 @@ public function add_notifications(Doku_Event $event) /** * @return array */ - protected function users_set($user_and_groups, $values) { + protected function usersSet($user_and_groups, $values) + { /** @var DokuWiki_Auth_Plugin $auth */ global $auth; + // $auth is missing in CLI context + if (is_null($auth)) { + auth_setup(); + } + //make substitutions $user_and_groups = preg_replace_callback( '/@@(.*?)@@/', function ($matches) use ($values) { - list($schema, $field) = explode('.', trim($matches[1])); + [$schema, $field] = explode('.', trim($matches[1])); if (!$field) return ''; /* @var Value $value */ foreach ($values as $value) { @@ -157,12 +171,15 @@ function ($matches) use ($values) { $colLabel = $column->getLabel(); $type = $column->getType(); if ($colLabel == $field) { - if (class_exists('\dokuwiki\plugin\structgroup\types\Group') && - $type instanceof \dokuwiki\plugin\structgroup\types\Group) { + if ( + class_exists('\dokuwiki\plugin\structgroup\types\Group') && + $type instanceof Group + ) { if ($column->isMulti()) { - return implode(',', array_map(function ($rawValue) { - return '@' . $rawValue; - }, $value->getRawValue())); + return implode( + ',', + array_map(static fn($rawValue) => '@' . $rawValue, $value->getRawValue()) + ); } else { return '@' . $value->getRawValue(); } @@ -203,7 +220,8 @@ function ($matches) use ($values) { return $set; } - protected function predicateTrue($date, $operator, $value) { + protected function predicateTrue($date, $operator, $value) + { $date = date('Y-m-d', strtotime($date)); switch ($operator) { @@ -222,7 +240,8 @@ protected function predicateTrue($date, $operator, $value) { } } - protected function replacePlaceholders($message, $values) { + protected function replacePlaceholders($message, $values) + { $patterns = []; $replacements = []; /* @var Value $value */ @@ -236,5 +255,22 @@ protected function replacePlaceholders($message, $values) { return preg_replace($patterns, $replacements, $message); } -} + /** + * @param Search $search + * @param string $filters + */ + protected function addFiltersToSearch(&$search, $filters) + { + if (!$filters) return; + /** @var \helper_plugin_struct_config $confHelper */ + $confHelper = plugin_load('helper', 'struct_config'); + + $filterConfigs = explode("\r\n", $filters); + + foreach ($filterConfigs as $config) { + [$colname, $comp, $value, ] = $confHelper->parseFilterLine('AND', $config); + $search->addFilter($colname, $value, $comp, 'AND'); + } + } +} diff --git a/admin.php b/admin.php index 9dbe35c..b524c3d 100644 --- a/admin.php +++ b/admin.php @@ -1,20 +1,17 @@ */ - -// must be run within Dokuwiki -if (!defined('DOKU_INC')) { - die(); -} - -class admin_plugin_structnotification extends DokuWiki_Admin_Plugin +class admin_plugin_structnotification extends AdminPlugin { - - protected $headers = ['schema', 'field', 'operator', 'value', 'users_and_groups', 'message']; + protected $headers = ['schema', 'field', 'operator', 'value', 'filters', 'users_and_groups', 'message']; protected $operators = ['before', 'after', 'at']; /** @@ -50,37 +47,33 @@ public function handle() return; } - if ($INPUT->str('action') && $INPUT->arr('predicate') && checkSecurityToken()) { $predicate = $INPUT->arr('predicate'); if ($INPUT->str('action') === 'add') { $errors = $this->validate($predicate); if ($errors) { - $this->display_errors($errors); + $this->displayErrors($errors); return; } $ok = $sqlite->storeEntry('predicate', $predicate); - if(!$ok) msg('failed to add predicate', -1); - } elseif($INPUT->str('action') === 'delete') { + if (!$ok) msg('failed to add predicate', -1); + } elseif ($INPUT->str('action') === 'delete') { $ok = $sqlite->query('DELETE FROM predicate WHERE id=?', $predicate['id']); - if(!$ok) msg('failed to delete predicate', -1); - } elseif($INPUT->str('action') === 'update') { + if (!$ok) msg('failed to delete predicate', -1); + } elseif ($INPUT->str('action') === 'update') { $errors = $this->validate($predicate); if ($errors) { - $this->display_errors($errors); + $this->displayErrors($errors); return; } - $set = implode(',', array_map(function ($header) { - return "$header=?"; - }, $this->headers)); + $set = implode(',', array_map(static fn($header) => "$header=?", $this->headers)); $predicate['id'] = $INPUT->str('edit'); $ok = $sqlite->query("UPDATE predicate SET $set WHERE id=?", $predicate); - if(!$ok) msg('failed to update predicate', -1); + if (!$ok) msg('failed to update predicate', -1); } - - if ($ok) send_redirect(wl($ID, array('do' => 'admin', 'page' => 'structnotification'), true, '&')); + if ($ok) send_redirect(wl($ID, ['do' => 'admin', 'page' => 'structnotification'], true, '&')); } } @@ -101,16 +94,15 @@ public function html() return; } - ptln('

' . $this->getLang('menu') . '

'); - ptln(''); + echo '

' . $this->getLang('menu') . '

'; + echo '
'; - ptln(''); + echo ''; foreach ($this->headers as $header) { - ptln(''); + echo ''; } - //extra field for buttons - ptln(''); - ptln(''); + echo ''; + echo ''; $q = 'SELECT * FROM predicate'; $res = $sqlite->query($q); @@ -123,64 +115,63 @@ public function html() $INPUT->set('predicate', $predicate); } - ptln($this->form('update')); + echo $this->form('update'); continue; } - ptln(''); + echo ''; foreach ($this->headers as $header) { $value = $predicate[$header]; if ($header == 'message') { - $html = p_render('xhtml',p_get_instructions($value), $info); - ptln(''); + $html = p_render('xhtml', p_get_instructions($value), $info); + echo ''; } else { - ptln(''); + echo ''; } } - ptln(''); - ptln(''); + echo ''; + echo ''; } if (!$INPUT->has('edit')) { - ptln($this->form()); + echo $this->form(); } - ptln('
' . $this->getLang('admin header '. $header) . '' . $this->getLang('admin header ' . $header) . '
' . $html . '' . $html . '' . $value . '' . $value . ''); + echo ''; $link = wl( - $ID, array( - 'do' => 'admin', - 'page' => 'structnotification', - 'edit' => $predicate['id'] - ) + $ID, + ['do' => 'admin', 'page' => 'structnotification', 'edit' => $predicate['id']] ); - ptln(''.$this->getLang('edit').' | '); + echo '' . $this->getLang('edit') . ' | '; $link = wl( - $ID, array( + $ID, + [ 'do' => 'admin', 'page' => 'structnotification', 'action' => 'delete', 'sectok' => getSecurityToken(), 'predicate[id]' => $predicate['id'] - ) + ] ); - ptln(''.$this->getLang('delete').''); + echo '' . + $this->getLang('delete') . ''; - ptln('
'); + echo ''; } - protected function form($action='add') + protected function form($action = 'add') { global $ID; - $form = new dokuwiki\Form\Form(); + $form = new Form(); $form->addTagOpen('tr'); $form->addTagOpen('td'); - $form->addTextInput('predicate[schema]')->attr('style', 'width: 8em'); + $form->addTextInput('predicate[schema]')->attr('size', 10); $form->addTagClose('td'); $form->addTagOpen('td'); - $form->addTextInput('predicate[field]')->attr('style', 'width: 8em'); + $form->addTextInput('predicate[field]')->attr('size', 10); $form->addTagClose('td'); $form->addTagOpen('td'); @@ -188,11 +179,19 @@ protected function form($action='add') $form->addTagClose('td'); $form->addTagOpen('td'); - $form->addTextInput('predicate[value]')->attr('style', 'width: 12em'); + $form->addTextInput('predicate[value]')->attr('size', 10); $form->addTagClose('td'); $form->addTagOpen('td'); - $form->addTextInput('predicate[users_and_groups]')->attr('style', 'width: 12em'); + $form->addTextarea('predicate[filters]') + ->attrs([ + 'cols' => '12', + 'rows' => '5' + ]); + $form->addTagClose('td'); + + $form->addTagOpen('td'); + $form->addTextInput('predicate[users_and_groups]')->attr('size', 10); $form->addTagClose('td'); $form->addTagOpen('td'); @@ -206,12 +205,14 @@ protected function form($action='add') $form->addTagOpen('td'); $form->addButton('action', $this->getLang($action))->val($action); $link = wl( - $ID, [ + $ID, + [ 'do' => 'admin', 'page' => 'structnotification', ] ); - $cancel_link = '' . $this->getLang('cancel') . ''; + $cancel_link = '' . + $this->getLang('cancel') . ''; $form->addHTML($cancel_link); $form->addTagClose('td'); @@ -251,7 +252,8 @@ protected function validate($predicate) return $errors; } - protected function display_errors($errors) { + protected function displayErrors($errors) + { foreach ($errors as $error) { $msg = $this->getLang($error); if (!$msg) $msg = $error; @@ -259,4 +261,3 @@ protected function display_errors($errors) { } } } - diff --git a/db/latest.version b/db/latest.version index 0cfbf08..00750ed 100644 --- a/db/latest.version +++ b/db/latest.version @@ -1 +1 @@ -2 +3 diff --git a/db/update0002.sql b/db/update0002.sql index 997df25..9a76aa0 100644 --- a/db/update0002.sql +++ b/db/update0002.sql @@ -12,4 +12,4 @@ INSERT INTO predicateTemp(id,schema,field,operator,value,users_and_groups,messag SELECT id,schema,field,operator,days,users_and_groups,message FROM predicate; DROP TABLE predicate; -ALTER TABLE predicateTemp RENAME TO predicate; \ No newline at end of file +ALTER TABLE predicateTemp RENAME TO predicate; diff --git a/db/update0003.sql b/db/update0003.sql new file mode 100644 index 0000000..0309889 --- /dev/null +++ b/db/update0003.sql @@ -0,0 +1 @@ +ALTER TABLE predicate ADD COLUMN filters TEXT DEFAULT ''; diff --git a/helper/db.php b/helper/db.php index d1c2ce9..7fa4934 100644 --- a/helper/db.php +++ b/helper/db.php @@ -1,18 +1,14 @@ */ - -// must be run within Dokuwiki - -if (!defined('DOKU_INC')) { - die(); -} - -class helper_plugin_structnotification_db extends DokuWiki_Plugin +class helper_plugin_structnotification_db extends Plugin { /** @var helper_plugin_sqlite */ protected $sqlite; @@ -32,7 +28,6 @@ public function __construct() */ protected function init() { - /** @var helper_plugin_sqlite $sqlite */ $this->sqlite = plugin_load('helper', 'sqlite'); if (!$this->sqlite) { if (defined('DOKU_UNITTEST')) { @@ -56,12 +51,11 @@ protected function init() throw new \Exception('Couldn\'t init sqlite.'); } $this->sqlite = null; - return; } } /** - * @return helper_plugin_sqlite|null + * @return helper_plugin_sqlite|null|bool */ public function getDB() { @@ -76,25 +70,4 @@ public function getDB() } return $this->sqlite; } - - /** - * Completely remove the database and reinitialize it - * - * You do not want to call this except for testing! - */ - public function resetDB() - { - if (!$this->sqlite) { - return; - } - $file = $this->sqlite->getAdapter()->getDbFile(); - if (!$file) { - return; - } - unlink($file); - clearstatcache(true, $file); - $this->init(); - } } - -// vim:ts=4:sw=4:et: diff --git a/lang/en/lang.php b/lang/en/lang.php index f77485f..e7e140f 100644 --- a/lang/en/lang.php +++ b/lang/en/lang.php @@ -12,6 +12,7 @@ $lang['admin header field'] = 'Field'; $lang['admin header operator'] = 'Operator'; $lang['admin header value'] = 'Value'; +$lang['admin header filters'] = 'Filters'; $lang['admin header users_and_groups'] = 'Users/Groups'; $lang['admin header message'] = 'Message';