xref: /plugin/structnotification/action/notification.php (revision e96b00ce614311bc1690b610d7467dc7a3323015)
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