1a1f4c7baSSzymon Olewniczak<?php 2a1f4c7baSSzymon Olewniczak/** 3a1f4c7baSSzymon Olewniczak * DokuWiki Plugin structnotification (Action Component) 4a1f4c7baSSzymon Olewniczak * 5a1f4c7baSSzymon Olewniczak * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 6a1f4c7baSSzymon Olewniczak * @author Szymon Olewniczak <it@rid.pl> 7a1f4c7baSSzymon Olewniczak */ 8a1f4c7baSSzymon Olewniczak 9922aade7SSzymon Olewniczakuse dokuwiki\plugin\struct\meta\Search; 10922aade7SSzymon Olewniczakuse dokuwiki\plugin\struct\meta\Value; 11922aade7SSzymon Olewniczak 12a1f4c7baSSzymon Olewniczakclass action_plugin_structnotification_notification extends DokuWiki_Action_Plugin 13a1f4c7baSSzymon Olewniczak{ 14a1f4c7baSSzymon Olewniczak 15a1f4c7baSSzymon Olewniczak /** 16a1f4c7baSSzymon Olewniczak * Registers a callback function for a given event 17a1f4c7baSSzymon Olewniczak * 18a1f4c7baSSzymon Olewniczak * @param Doku_Event_Handler $controller DokuWiki's event controller object 19a1f4c7baSSzymon Olewniczak * 20a1f4c7baSSzymon Olewniczak * @return void 21a1f4c7baSSzymon Olewniczak */ 22a1f4c7baSSzymon Olewniczak public function register(Doku_Event_Handler $controller) 23a1f4c7baSSzymon Olewniczak { 24922aade7SSzymon Olewniczak $controller->register_hook('PLUGIN_NOTIFICATION_REGISTER_SOURCE', 'AFTER', $this, 'add_notifications_source'); 25922aade7SSzymon Olewniczak $controller->register_hook('PLUGIN_NOTIFICATION_GATHER', 'AFTER', $this, 'add_notifications'); 26922aade7SSzymon Olewniczak $controller->register_hook('PLUGIN_NOTIFICATION_CACHE_DEPENDENCIES', 'AFTER', $this, 'add_notification_cache_dependencies'); 27922aade7SSzymon Olewniczak } 28922aade7SSzymon Olewniczak 29922aade7SSzymon Olewniczak public function add_notifications_source(Doku_Event $event) 30922aade7SSzymon Olewniczak { 31922aade7SSzymon Olewniczak $event->data[] = 'structnotification'; 32922aade7SSzymon Olewniczak } 33922aade7SSzymon Olewniczak 34922aade7SSzymon Olewniczak public function add_notification_cache_dependencies(Doku_Event $event) 35922aade7SSzymon Olewniczak { 36922aade7SSzymon Olewniczak if (!in_array('structnotification', $event->data['plugins'])) return; 37922aade7SSzymon Olewniczak 38922aade7SSzymon Olewniczak try { 39922aade7SSzymon Olewniczak /** @var \helper_plugin_structnotification_db $db_helper */ 40922aade7SSzymon Olewniczak $db_helper = plugin_load('helper', 'structnotification_db'); 41922aade7SSzymon Olewniczak $sqlite = $db_helper->getDB(); 42922aade7SSzymon Olewniczak $event->data['dependencies'][] = $sqlite->getAdapter()->getDbFile(); 43922aade7SSzymon Olewniczak } catch (Exception $e) { 44922aade7SSzymon Olewniczak msg($e->getMessage(), -1); 45922aade7SSzymon Olewniczak return; 46922aade7SSzymon Olewniczak } 47922aade7SSzymon Olewniczak } 48922aade7SSzymon Olewniczak 49922aade7SSzymon Olewniczak protected function getValueByLabel($values, $label) 50922aade7SSzymon Olewniczak { 51922aade7SSzymon Olewniczak /* @var Value $value */ 52922aade7SSzymon Olewniczak foreach ($values as $value) { 53922aade7SSzymon Olewniczak $colLabel = $value->getColumn()->getLabel(); 54922aade7SSzymon Olewniczak if ($colLabel == $label) { 55922aade7SSzymon Olewniczak return $value->getRawValue(); 56922aade7SSzymon Olewniczak } 57922aade7SSzymon Olewniczak } 58922aade7SSzymon Olewniczak //nothing found 59922aade7SSzymon Olewniczak throw new Exception("column: $label not found in values"); 60922aade7SSzymon Olewniczak } 61922aade7SSzymon Olewniczak 62922aade7SSzymon Olewniczak public function add_notifications(Doku_Event $event) 63922aade7SSzymon Olewniczak { 64922aade7SSzymon Olewniczak if (!in_array('structnotification', $event->data['plugins'])) return; 65922aade7SSzymon Olewniczak 66922aade7SSzymon Olewniczak try { 67922aade7SSzymon Olewniczak /** @var \helper_plugin_structnotification_db$db_helper */ 68922aade7SSzymon Olewniczak $db_helper = plugin_load('helper', 'structnotification_db'); 69922aade7SSzymon Olewniczak $sqlite = $db_helper->getDB(); 70922aade7SSzymon Olewniczak } catch (Exception $e) { 71922aade7SSzymon Olewniczak msg($e->getMessage(), -1); 72922aade7SSzymon Olewniczak return; 73922aade7SSzymon Olewniczak } 74922aade7SSzymon Olewniczak 75922aade7SSzymon Olewniczak $user = $event->data['user']; 76922aade7SSzymon Olewniczak 77922aade7SSzymon Olewniczak $q = 'SELECT * FROM predicate'; 78922aade7SSzymon Olewniczak $res = $sqlite->query($q); 79922aade7SSzymon Olewniczak 80922aade7SSzymon Olewniczak $predicates = $sqlite->res2arr($res); 81922aade7SSzymon Olewniczak 82922aade7SSzymon Olewniczak foreach ($predicates as $predicate) { 83922aade7SSzymon Olewniczak $schema = $predicate['schema']; 84922aade7SSzymon Olewniczak $field = $predicate['field']; 85922aade7SSzymon Olewniczak $operator = $predicate['operator']; 864677fc3cSSzymon Olewniczak $value = $predicate['value']; 87*e96b00ceSAnna Dabrowska $filters = $predicate['filters']; 88922aade7SSzymon Olewniczak $users_and_groups = $predicate['users_and_groups']; 89922aade7SSzymon Olewniczak $message = $predicate['message']; 90922aade7SSzymon Olewniczak 91922aade7SSzymon Olewniczak try { 92922aade7SSzymon Olewniczak $search = new Search(); 934677fc3cSSzymon Olewniczak foreach (explode(',', $schema) as $table) { 944677fc3cSSzymon Olewniczak $search->addSchema($table); 954677fc3cSSzymon Olewniczak $search->addColumn($table . '.*'); 964677fc3cSSzymon Olewniczak } 97115044e5SSzymon Olewniczak // add special columns 98115044e5SSzymon Olewniczak $special_columns = ['%pageid%', '%title%', '%lastupdate%', '%lasteditor%', '%lastsummary%', '%rowid%']; 99115044e5SSzymon Olewniczak foreach ($special_columns as $special_column) { 100115044e5SSzymon Olewniczak $search->addColumn($special_column); 101115044e5SSzymon Olewniczak } 102*e96b00ceSAnna Dabrowska $this->addFiltersToSearch($search, $filters); 103922aade7SSzymon Olewniczak $result = $search->execute(); 104922aade7SSzymon Olewniczak $result_pids = $search->getPids(); 105922aade7SSzymon Olewniczak 106922aade7SSzymon Olewniczak /* @var Value[] $row */ 107922aade7SSzymon Olewniczak for ($i = 0; $i < count($result); $i++) { 108922aade7SSzymon Olewniczak $values = $result[$i]; 109922aade7SSzymon Olewniczak $pid = $result_pids[$i]; 1102c65b673SSzymon Olewniczak 1112c65b673SSzymon Olewniczak $users_set = $this->users_set($users_and_groups, $values); 1122c65b673SSzymon Olewniczak if (!isset($users_set[$user])) continue; 1132c65b673SSzymon Olewniczak 114922aade7SSzymon Olewniczak $rawDate = $this->getValueByLabel($values, $field); 1154677fc3cSSzymon Olewniczak if ($this->predicateTrue($rawDate, $operator, $value)) { 116c0d6a71fSSzymon Olewniczak $message_with_replacements = $this->replacePlaceholders($message, $values); 117c0d6a71fSSzymon Olewniczak $message_with_replacements_html = p_render('xhtml', 118c0d6a71fSSzymon Olewniczak p_get_instructions($message_with_replacements), $info); 119922aade7SSzymon Olewniczak $event->data['notifications'][] = [ 120922aade7SSzymon Olewniczak 'plugin' => 'structnotification', 121922aade7SSzymon Olewniczak 'id' => $predicate['id'] . ':'. $schema . ':' . $pid . ':' . $rawDate, 122c0d6a71fSSzymon Olewniczak 'full' => $message_with_replacements_html, 123c0d6a71fSSzymon Olewniczak 'brief' => $message_with_replacements_html, 124922aade7SSzymon Olewniczak 'timestamp' => (int) strtotime($rawDate) 125922aade7SSzymon Olewniczak ]; 126922aade7SSzymon Olewniczak } 127922aade7SSzymon Olewniczak } 128922aade7SSzymon Olewniczak } catch (Exception $e) { 129922aade7SSzymon Olewniczak msg($e->getMessage(), -1); 130922aade7SSzymon Olewniczak return; 131922aade7SSzymon Olewniczak } 132922aade7SSzymon Olewniczak } 133a1f4c7baSSzymon Olewniczak } 134a1f4c7baSSzymon Olewniczak 135a1f4c7baSSzymon Olewniczak /** 136922aade7SSzymon Olewniczak * @return array 137a1f4c7baSSzymon Olewniczak */ 1382c65b673SSzymon Olewniczak protected function users_set($user_and_groups, $values) { 139922aade7SSzymon Olewniczak /** @var DokuWiki_Auth_Plugin $auth */ 140922aade7SSzymon Olewniczak global $auth; 141922aade7SSzymon Olewniczak 1422c65b673SSzymon Olewniczak //make substitutions 1432c65b673SSzymon Olewniczak $user_and_groups = preg_replace_callback( 1442c65b673SSzymon Olewniczak '/@@(.*?)@@/', 1452c65b673SSzymon Olewniczak function ($matches) use ($values) { 1462c65b673SSzymon Olewniczak list($schema, $field) = explode('.', trim($matches[1])); 1472c65b673SSzymon Olewniczak if (!$field) return ''; 1482c65b673SSzymon Olewniczak /* @var Value $value */ 1492c65b673SSzymon Olewniczak foreach ($values as $value) { 15086ba6958SSzymon Olewniczak $column = $value->getColumn(); 15186ba6958SSzymon Olewniczak $colLabel = $column->getLabel(); 15286ba6958SSzymon Olewniczak $type = $column->getType(); 1532c65b673SSzymon Olewniczak if ($colLabel == $field) { 1542c65b673SSzymon Olewniczak if (class_exists('\dokuwiki\plugin\structgroup\types\Group') && 1552c65b673SSzymon Olewniczak $type instanceof \dokuwiki\plugin\structgroup\types\Group) { 15686ba6958SSzymon Olewniczak if ($column->isMulti()) { 15786ba6958SSzymon Olewniczak return implode(',', array_map(function ($rawValue) { 15886ba6958SSzymon Olewniczak return '@' . $rawValue; 15986ba6958SSzymon Olewniczak }, $value->getRawValue())); 16086ba6958SSzymon Olewniczak } else { 1612c65b673SSzymon Olewniczak return '@' . $value->getRawValue(); 1622c65b673SSzymon Olewniczak } 16386ba6958SSzymon Olewniczak } 16486ba6958SSzymon Olewniczak if ($column->isMulti()) { 16586ba6958SSzymon Olewniczak return implode(',', $value->getRawValue()); 16686ba6958SSzymon Olewniczak } else { 1672c65b673SSzymon Olewniczak return $value->getRawValue(); 1682c65b673SSzymon Olewniczak } 1692c65b673SSzymon Olewniczak } 17086ba6958SSzymon Olewniczak } 1712c65b673SSzymon Olewniczak return ''; 1722c65b673SSzymon Olewniczak }, 1732c65b673SSzymon Olewniczak $user_and_groups 1742c65b673SSzymon Olewniczak ); 1752c65b673SSzymon Olewniczak 176922aade7SSzymon Olewniczak $user_and_groups_set = array_map('trim', explode(',', $user_and_groups)); 177922aade7SSzymon Olewniczak $users = []; 178922aade7SSzymon Olewniczak $groups = []; 179922aade7SSzymon Olewniczak foreach ($user_and_groups_set as $user_or_group) { 180922aade7SSzymon Olewniczak if ($user_or_group[0] == '@') { 181922aade7SSzymon Olewniczak $groups[] = substr($user_or_group, 1); 182922aade7SSzymon Olewniczak } else { 183922aade7SSzymon Olewniczak $users[] = $user_or_group; 184a1f4c7baSSzymon Olewniczak } 185a1f4c7baSSzymon Olewniczak } 186922aade7SSzymon Olewniczak $set = []; 187922aade7SSzymon Olewniczak 188922aade7SSzymon Olewniczak $all_users = $auth->retrieveUsers(); 189922aade7SSzymon Olewniczak foreach ($all_users as $user => $info) { 190922aade7SSzymon Olewniczak if (in_array($user, $users)) { 191922aade7SSzymon Olewniczak $set[$user] = $info; 192922aade7SSzymon Olewniczak } elseif (array_intersect($groups, $info['grps'])) { 193922aade7SSzymon Olewniczak $set[$user] = $info; 194922aade7SSzymon Olewniczak } 195922aade7SSzymon Olewniczak } 196922aade7SSzymon Olewniczak 197922aade7SSzymon Olewniczak return $set; 198922aade7SSzymon Olewniczak } 199922aade7SSzymon Olewniczak 2004677fc3cSSzymon Olewniczak protected function predicateTrue($date, $operator, $value) { 201922aade7SSzymon Olewniczak $date = date('Y-m-d', strtotime($date)); 202922aade7SSzymon Olewniczak 203922aade7SSzymon Olewniczak switch ($operator) { 204922aade7SSzymon Olewniczak case 'before': 2054677fc3cSSzymon Olewniczak $days = date('Y-m-d', strtotime("+$value days")); 206922aade7SSzymon Olewniczak return $days >= $date; 207922aade7SSzymon Olewniczak case 'after': 2084677fc3cSSzymon Olewniczak $days = date('Y-m-d', strtotime("-$value days")); 209922aade7SSzymon Olewniczak return $date <= $days; 2104677fc3cSSzymon Olewniczak case 'at': 2114677fc3cSSzymon Olewniczak $now = new DateTime(); 2124677fc3cSSzymon Olewniczak $at = new DateTime(date($value, strtotime($date))); 2134677fc3cSSzymon Olewniczak return $now >= $at; 214922aade7SSzymon Olewniczak default: 215922aade7SSzymon Olewniczak return false; 216922aade7SSzymon Olewniczak } 217a1f4c7baSSzymon Olewniczak } 218a1f4c7baSSzymon Olewniczak 219ac63f65fSSzymon Olewniczak protected function replacePlaceholders($message, $values) { 220ac63f65fSSzymon Olewniczak $patterns = []; 221ac63f65fSSzymon Olewniczak $replacements = []; 222ac63f65fSSzymon Olewniczak /* @var Value $value */ 223ac63f65fSSzymon Olewniczak foreach ($values as $value) { 224ac63f65fSSzymon Olewniczak $schema = $value->getColumn()->getTable(); 225ac63f65fSSzymon Olewniczak $label = $value->getColumn()->getLabel(); 226ac63f65fSSzymon Olewniczak $patterns[] = "/@@$schema.$label@@/"; 227ac63f65fSSzymon Olewniczak $replacements[] = $value->getDisplayValue(); 228ac63f65fSSzymon Olewniczak } 229ac63f65fSSzymon Olewniczak 230ac63f65fSSzymon Olewniczak return preg_replace($patterns, $replacements, $message); 231ac63f65fSSzymon Olewniczak } 232ac63f65fSSzymon Olewniczak 233*e96b00ceSAnna Dabrowska /** 234*e96b00ceSAnna Dabrowska * @param Search $search 235*e96b00ceSAnna Dabrowska * @param string $filters 236*e96b00ceSAnna Dabrowska */ 237*e96b00ceSAnna Dabrowska protected function addFiltersToSearch(&$search, $filters) 238*e96b00ceSAnna Dabrowska { 239*e96b00ceSAnna Dabrowska if (!$filters) return; 240a1f4c7baSSzymon Olewniczak 241*e96b00ceSAnna Dabrowska /** @var \helper_plugin_struct_config $confHelper */ 242*e96b00ceSAnna Dabrowska $confHelper = plugin_load('helper', 'struct_config'); 243*e96b00ceSAnna Dabrowska 244*e96b00ceSAnna Dabrowska $filterConfigs = explode("\r\n", $filters); 245*e96b00ceSAnna Dabrowska 246*e96b00ceSAnna Dabrowska foreach ($filterConfigs as $config) { 247*e96b00ceSAnna Dabrowska list($colname, $comp, $value,) = $confHelper->parseFilterLine('AND', $config); 248*e96b00ceSAnna Dabrowska $search->addFilter($colname, $value, $comp, 'AND'); 249*e96b00ceSAnna Dabrowska } 250*e96b00ceSAnna Dabrowska } 251*e96b00ceSAnna Dabrowska} 252