1<?php
2
3use dokuwiki\Extension\Plugin;
4use dokuwiki\Extension\Event;
5
6/**
7 * DokuWiki Plugin notification (Helper Component)
8 *
9 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
10 */
11class helper_plugin_notification_cron extends Plugin
12{
13    /** @var helper_plugin_sqlite */
14    protected $sqlite;
15
16    public function __construct()
17    {
18        /** @var \helper_plugin_notification_db $db_helper */
19        $db_helper = plugin_load('helper', 'notification_db');
20        $this->sqlite = $db_helper->getDB();
21    }
22
23    public function addUsersToCron()
24    {
25        /** @var DokuWiki_Auth_Plugin $auth */
26        global $auth;
27
28        $res = $this->sqlite->query('SELECT user from cron_check');
29        $ourUsers = $this->sqlite->res2arr($res);
30
31        $ourUsers = array_map(function ($item) {
32            return $item['user'];
33        }, $ourUsers);
34
35        $allUsers = array_keys($auth->retrieveUsers());
36
37        $newUsers = array_diff($allUsers, $ourUsers);
38
39        if (!is_array($newUsers) || $newUsers === []) return;
40
41        foreach ($newUsers as $user) {
42            $this->sqlite->storeEntry(
43                'cron_check',
44                ['user' => $user, 'timestamp' => date('c', 0)]
45            );
46        }
47    }
48
49    /**
50     * Gather notification data from plugins
51     *
52     * @param string $user
53     * @return array
54     */
55    public function getNotificationData($user)
56    {
57        $plugins = [];
58        $event = new Event('PLUGIN_NOTIFICATION_REGISTER_SOURCE', $plugins);
59        $event->trigger();
60
61        $notifications_data = [
62            'plugins' => $plugins,
63            'user' => $user,
64            'notifications' => []
65        ];
66        $event = new Event('PLUGIN_NOTIFICATION_GATHER', $notifications_data);
67        $event->trigger();
68
69        if (!empty($notifications_data['notifications'])) {
70            $notifications = $notifications_data['notifications'];
71
72            // get only notifications that have ids
73            $notifications_data['notifications'] = array_filter($notifications, function ($notification) {
74                return array_key_exists('id', $notification);
75            });
76        }
77
78        return $notifications_data;
79    }
80
81    /**
82     * Prune old (already sent) notifications and return only new ones
83     *
84     * @param string $user
85     * @param array $notification_data
86     * @return array
87     */
88    public function getNewNotifications($user, $notification_data)
89    {
90        /** @var \helper_plugin_notification_db $db_helper */
91        $db_helper = plugin_load('helper', 'notification_db');
92        $sqlite = $db_helper->getDB();
93
94        $notifications = $notification_data['notifications'];
95        $plugins = $notification_data['plugins'];
96
97        //get the notifications that have been sent already
98        $res = $sqlite->query('SELECT plugin, notification_id FROM notification WHERE user=?', $user);
99        $sent_notifications = $sqlite->res2arr($res);
100        $sent_notifications_by_plugin = [];
101        foreach ($plugins as $plugin) {
102            $sent_notifications_by_plugin[$plugin] = [];
103        }
104        foreach ($sent_notifications as $sent_notification) {
105            $plugin = $sent_notification['plugin'];
106            $id = $sent_notification['notification_id'];
107            $sent_notifications_by_plugin[$plugin][$id] = true;
108        }
109
110        // keep only notifications not yet sent
111        $new_notifications = [];
112        foreach ($notifications as $notification) {
113            $plugin = $notification['plugin'];
114            $id = $notification['id'];
115            if (!isset($sent_notifications_by_plugin[$plugin][$id])) {
116                $new_notifications[] = $notification;
117            }
118        }
119
120        return $new_notifications;
121    }
122
123    /**
124     * Create text and HTML components of email message
125     *
126     * @param array $new_notifications
127     * @return string[]
128     */
129    public function composeEmail($new_notifications)
130    {
131        $html = '<p>' . $this->getLang('mail content') . '</p>';
132        $html .= '<ul>';
133        $text = $this->getLang('mail content') . "\n\n";
134
135        usort($new_notifications, function ($a, $b) {
136            if ($a['timestamp'] == $b['timestamp']) {
137                return 0;
138            }
139            return ($a['timestamp'] > $b['timestamp']) ? -1 : 1;
140        });
141
142        foreach ($new_notifications as $notification) {
143            $content = $notification['full'];
144            $timestamp = $notification['timestamp'];
145
146            $date = strftime('%d.%m %H:%M', $timestamp);
147
148            $html .= "<li class=\"level1\"><div class=\"li\">$date $content</div></li>";
149            $text .= $date . ' ' . strip_tags($content) . "\n";
150        }
151        $html .= '</ul>';
152
153        return [$text, $html];
154    }
155
156    /**
157     * Send notification email to the given user
158     *
159     * @param string $user
160     * @param string $text
161     * @param string $html
162     * @return bool true if email was sent successfully
163     */
164    public function sendMail($user, $text, $html)
165    {
166        /** @var DokuWiki_Auth_Plugin $auth */
167        global $auth;
168
169        $mail = new Mailer();
170        $userinfo = $auth->getUserData($user, false);
171        $mail->to($userinfo['name'] . ' <' . $userinfo['mail'] . '>');
172        $mail->subject($this->getLang('mail subject'));
173        $mail->setBody($text, null, null, $html);
174        return $mail->send();
175    }
176
177    /**
178     * Store info about sent notifications
179     *
180     * @param string $user
181     * @param array $notifications
182     */
183    public function storeSentNotifications($user, $notifications)
184    {
185        /** @var \helper_plugin_notification_db $db_helper */
186        $db_helper = plugin_load('helper', 'notification_db');
187        $sqlite = $db_helper->getDB();
188
189        foreach ($notifications as $notification) {
190            $plugin = $notification['plugin'];
191            $id = $notification['id'];
192            $sqlite->storeEntry(
193                'notification',
194                ['plugin' => $plugin, 'notification_id' => $id, 'user' => $user, 'sent' => date('c')]
195            );
196        }
197    }
198}
199