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']; 87e96b00ceSAnna 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 } 102e96b00ceSAnna 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 142*cfa4f911SAnna Dabrowska // $auth is missing in CLI context 143*cfa4f911SAnna Dabrowska if (is_null($auth)) { 144*cfa4f911SAnna Dabrowska auth_setup(); 145*cfa4f911SAnna Dabrowska } 146*cfa4f911SAnna Dabrowska 1472c65b673SSzymon Olewniczak //make substitutions 1482c65b673SSzymon Olewniczak $user_and_groups = preg_replace_callback( 1492c65b673SSzymon Olewniczak '/@@(.*?)@@/', 1502c65b673SSzymon Olewniczak function ($matches) use ($values) { 1512c65b673SSzymon Olewniczak list($schema, $field) = explode('.', trim($matches[1])); 1522c65b673SSzymon Olewniczak if (!$field) return ''; 1532c65b673SSzymon Olewniczak /* @var Value $value */ 1542c65b673SSzymon Olewniczak foreach ($values as $value) { 15586ba6958SSzymon Olewniczak $column = $value->getColumn(); 15686ba6958SSzymon Olewniczak $colLabel = $column->getLabel(); 15786ba6958SSzymon Olewniczak $type = $column->getType(); 1582c65b673SSzymon Olewniczak if ($colLabel == $field) { 1592c65b673SSzymon Olewniczak if (class_exists('\dokuwiki\plugin\structgroup\types\Group') && 1602c65b673SSzymon Olewniczak $type instanceof \dokuwiki\plugin\structgroup\types\Group) { 16186ba6958SSzymon Olewniczak if ($column->isMulti()) { 16286ba6958SSzymon Olewniczak return implode(',', array_map(function ($rawValue) { 16386ba6958SSzymon Olewniczak return '@' . $rawValue; 16486ba6958SSzymon Olewniczak }, $value->getRawValue())); 16586ba6958SSzymon Olewniczak } else { 1662c65b673SSzymon Olewniczak return '@' . $value->getRawValue(); 1672c65b673SSzymon Olewniczak } 16886ba6958SSzymon Olewniczak } 16986ba6958SSzymon Olewniczak if ($column->isMulti()) { 17086ba6958SSzymon Olewniczak return implode(',', $value->getRawValue()); 17186ba6958SSzymon Olewniczak } else { 1722c65b673SSzymon Olewniczak return $value->getRawValue(); 1732c65b673SSzymon Olewniczak } 1742c65b673SSzymon Olewniczak } 17586ba6958SSzymon Olewniczak } 1762c65b673SSzymon Olewniczak return ''; 1772c65b673SSzymon Olewniczak }, 1782c65b673SSzymon Olewniczak $user_and_groups 1792c65b673SSzymon Olewniczak ); 1802c65b673SSzymon Olewniczak 181922aade7SSzymon Olewniczak $user_and_groups_set = array_map('trim', explode(',', $user_and_groups)); 182922aade7SSzymon Olewniczak $users = []; 183922aade7SSzymon Olewniczak $groups = []; 184922aade7SSzymon Olewniczak foreach ($user_and_groups_set as $user_or_group) { 185922aade7SSzymon Olewniczak if ($user_or_group[0] == '@') { 186922aade7SSzymon Olewniczak $groups[] = substr($user_or_group, 1); 187922aade7SSzymon Olewniczak } else { 188922aade7SSzymon Olewniczak $users[] = $user_or_group; 189a1f4c7baSSzymon Olewniczak } 190a1f4c7baSSzymon Olewniczak } 191922aade7SSzymon Olewniczak $set = []; 192922aade7SSzymon Olewniczak 193922aade7SSzymon Olewniczak $all_users = $auth->retrieveUsers(); 194922aade7SSzymon Olewniczak foreach ($all_users as $user => $info) { 195922aade7SSzymon Olewniczak if (in_array($user, $users)) { 196922aade7SSzymon Olewniczak $set[$user] = $info; 197922aade7SSzymon Olewniczak } elseif (array_intersect($groups, $info['grps'])) { 198922aade7SSzymon Olewniczak $set[$user] = $info; 199922aade7SSzymon Olewniczak } 200922aade7SSzymon Olewniczak } 201922aade7SSzymon Olewniczak 202922aade7SSzymon Olewniczak return $set; 203922aade7SSzymon Olewniczak } 204922aade7SSzymon Olewniczak 2054677fc3cSSzymon Olewniczak protected function predicateTrue($date, $operator, $value) { 206922aade7SSzymon Olewniczak $date = date('Y-m-d', strtotime($date)); 207922aade7SSzymon Olewniczak 208922aade7SSzymon Olewniczak switch ($operator) { 209922aade7SSzymon Olewniczak case 'before': 2104677fc3cSSzymon Olewniczak $days = date('Y-m-d', strtotime("+$value days")); 211922aade7SSzymon Olewniczak return $days >= $date; 212922aade7SSzymon Olewniczak case 'after': 2134677fc3cSSzymon Olewniczak $days = date('Y-m-d', strtotime("-$value days")); 214922aade7SSzymon Olewniczak return $date <= $days; 2154677fc3cSSzymon Olewniczak case 'at': 2164677fc3cSSzymon Olewniczak $now = new DateTime(); 2174677fc3cSSzymon Olewniczak $at = new DateTime(date($value, strtotime($date))); 2184677fc3cSSzymon Olewniczak return $now >= $at; 219922aade7SSzymon Olewniczak default: 220922aade7SSzymon Olewniczak return false; 221922aade7SSzymon Olewniczak } 222a1f4c7baSSzymon Olewniczak } 223a1f4c7baSSzymon Olewniczak 224ac63f65fSSzymon Olewniczak protected function replacePlaceholders($message, $values) { 225ac63f65fSSzymon Olewniczak $patterns = []; 226ac63f65fSSzymon Olewniczak $replacements = []; 227ac63f65fSSzymon Olewniczak /* @var Value $value */ 228ac63f65fSSzymon Olewniczak foreach ($values as $value) { 229ac63f65fSSzymon Olewniczak $schema = $value->getColumn()->getTable(); 230ac63f65fSSzymon Olewniczak $label = $value->getColumn()->getLabel(); 231ac63f65fSSzymon Olewniczak $patterns[] = "/@@$schema.$label@@/"; 232ac63f65fSSzymon Olewniczak $replacements[] = $value->getDisplayValue(); 233ac63f65fSSzymon Olewniczak } 234ac63f65fSSzymon Olewniczak 235ac63f65fSSzymon Olewniczak return preg_replace($patterns, $replacements, $message); 236ac63f65fSSzymon Olewniczak } 237ac63f65fSSzymon Olewniczak 238e96b00ceSAnna Dabrowska /** 239e96b00ceSAnna Dabrowska * @param Search $search 240e96b00ceSAnna Dabrowska * @param string $filters 241e96b00ceSAnna Dabrowska */ 242e96b00ceSAnna Dabrowska protected function addFiltersToSearch(&$search, $filters) 243e96b00ceSAnna Dabrowska { 244e96b00ceSAnna Dabrowska if (!$filters) return; 245a1f4c7baSSzymon Olewniczak 246e96b00ceSAnna Dabrowska /** @var \helper_plugin_struct_config $confHelper */ 247e96b00ceSAnna Dabrowska $confHelper = plugin_load('helper', 'struct_config'); 248e96b00ceSAnna Dabrowska 249e96b00ceSAnna Dabrowska $filterConfigs = explode("\r\n", $filters); 250e96b00ceSAnna Dabrowska 251e96b00ceSAnna Dabrowska foreach ($filterConfigs as $config) { 252e96b00ceSAnna Dabrowska list($colname, $comp, $value,) = $confHelper->parseFilterLine('AND', $config); 253e96b00ceSAnna Dabrowska $search->addFilter($colname, $value, $comp, 'AND'); 254e96b00ceSAnna Dabrowska } 255e96b00ceSAnna Dabrowska } 256e96b00ceSAnna Dabrowska} 257