source: trunk/Modules/Notify/Notify.php

Last change on this file was 972, checked in by chronos, 4 months ago
  • Fixed: Wrong class properties accessed in Notify RSS channel creation.
File size: 7.9 KB
Line 
1<?php
2
3define('CONTACT_CATEGORY_EMAIL', 4);
4
5class ModuleNotify extends Module
6{
7 public array $Checks;
8
9 function __construct(System $System)
10 {
11 parent::__construct($System);
12 $this->Name = 'Notify';
13 $this->Version = '1.0';
14 $this->Creator = 'Chronos';
15 $this->License = 'GNU/GPLv3';
16 $this->Description = 'Send notification messages to selected users';
17 $this->Dependencies = array(ModuleUser::GetName(), ModuleRSS::GetName());
18 $this->Models = array(NotifyCategory::GetClassName(), NotifyUser::GetClassName());
19
20 $this->Checks = array();
21 }
22
23 function DoStart(): void
24 {
25 $this->System->FormManager->RegisterClass('NotifyUser', array(
26 'Title' => 'Upozornění uživatelé',
27 'Table' => 'NotifyUser',
28 'Items' => array(
29 'User' => array('Type' => 'TUser', 'Caption' => 'Uživatel', 'Default' => ''),
30 'Contact' => array('Type' => 'TContact', 'Caption' => 'Kontakt', 'Default' => ''),
31 'Period' => array('Type' => 'Integer', 'Caption' => 'Interval', 'Default' => '60'),
32 ),
33 ));
34 $this->System->FormManager->RegisterClass('NotifyCategory', array(
35 'Title' => 'Kategorie upozornění',
36 'Table' => 'NotifyCategory',
37 'Items' => array(
38 'Name' => array('Type' => 'String', 'Caption' => 'Jméno', 'Default' => ''),
39 'SysName' => array('Type' => 'String', 'Caption' => 'Systémové jméno', 'Default' => ''),
40 ),
41 ));
42 $this->System->RegisterPage(['notify'], 'PageNotify');
43 $this->System->RegisterCommandLine('notify', 'Perform notifications processing.', array($this, 'RunCheck'));
44 ModuleRSS::Cast($this->System->GetModule('RSS'))->RegisterRSS(array('Title' => 'Notify log',
45 'Channel' => 'notifylog', 'Callback' => array($this, 'ShowLogRSS'),
46 'Permission' => array('Module' => 'Notify', 'Operation' => 'RSS')));
47 }
48
49 function RegisterCheck(string $Name, callable $Callback): void
50 {
51 if (array_key_exists($Name, $this->Checks))
52 throw new Exception('Check function "'.$Name.'" already registered.');
53 $this->Checks[$Name] = array('Callback' => $Callback);
54 }
55
56 function UnregisterCheck(string $Name): void
57 {
58 if (!array_key_exists($Name, $this->Checks))
59 throw new Exception('Check function "'.$Name.'" not registered.');
60 unset($this->Checks[$Name]);
61 }
62
63 function Check(): string
64 {
65 $Output = '';
66 $Content = '';
67 $Title = '';
68
69 // Get output from checks
70 $DbResult2 = $this->Database->query('SELECT `Id`, `Name`, `SysName` FROM `NotifyCategory`');
71 while ($Category = $DbResult2->fetch_assoc())
72 {
73 if (array_key_exists($Category['SysName'], $this->Checks))
74 {
75 $Status = call_user_func($this->Checks[$Category['SysName']]['Callback']);
76 if ($Status['Report'] != '')
77 {
78 $Output .= 'Kategorie: '.$Category['Name'].":\n";
79 $Content .= 'Kategorie: '.$Category['Name']."<br>\n";
80 $Content .= $Status['Report'];
81 }
82 if (strlen($Title) > 0) $Title .= ', ';
83 $Title .= $Status['Title'].':'.$Status['Count'];
84 }
85 }
86
87 $Time = time();
88
89 // Send content to users
90 $DbResult = $this->Database->query('SELECT `NotifyUser`.`Id`, `NotifyUser`.`LastTime`, `User`.`Name`, `Contact`.`Value`, `Contact`.`Category` FROM `NotifyUser` '.
91 'LEFT JOIN `User` ON `User`.`Id` = `NotifyUser`.`User` '.
92 'LEFT JOIN `Contact` ON `Contact`.`Id` = `NotifyUser`.`Contact`');
93 while ($User = $DbResult->fetch_assoc())
94 {
95 $Output .= 'User '.$User['Name'].'<br/>';
96
97 $this->Database->update('NotifyUser', '`Id`='.$User['Id'], array('LastTime' => TimeToMysqlDateTime($Time)));
98
99 if (($User['Category'] == CONTACT_CATEGORY_EMAIL) and ($Content != ''))
100 {
101 $Mail = new Mail();
102 $Mail->Subject = $Title;
103 $Mail->From = $this->System->Config['Web']['Title'].' <noreplay@zdechov.net>';
104 $Mail->AddTo($User['Value'], $User['Name']);
105 $Mail->AddBody(strip_tags($Content), 'text/plain');
106 $Mail->AddBody('<style>
107table { border-collapse: collapse; }
108table, th, td { border: 1px solid black; }
109td { padding: 5px; }
110 </style>'.$Content, 'text/html');
111 $Mail->Send();
112 $Output .= 'Sent email to '.$User['Value'].' ('.$User['Name'].')<br/>';
113 $Output .= strip_tags(str_replace("</", " </", str_replace('<br/>', "\n", $Content)));
114 }
115 }
116
117 if ($Content != '')
118 {
119 $this->Database->insert('NotifyLog', array(
120 'Time' => TimeToMysqlDateTime($Time),
121 'Title' => $Title,
122 'Content' => $Content)
123 );
124 }
125
126 return $Output;
127 }
128
129 function RunCheck(array $Parameters): void
130 {
131 RepeatFunction(30, array($this, 'Check'));
132 }
133
134 function DoInstall(): void
135 {
136 $this->Database->query("INSERT INTO `NotifyCategory` (`Id`, `Name`, `SysName`) VALUES
137 (1, 'Dostupnost zařízení (ping)', 'NetworkReachability'),
138 (2, 'Dostupnost URL', 'URL'),
139 (3, 'Minimální úroveň signálu', 'WirelessSignal'),
140 (4, 'Dostupnost síťového portu', 'NetworkPort'),
141 (5, 'Minimální odezva', 'NetworkLatency'),
142 (6, 'Minimální propustnost', 'NetworkBandwidth');");
143 }
144
145 function ShowLogRSS(): string
146 {
147 Header('Content-Type: text/xml');
148 $Count = 20;
149
150 $Items = array();
151 $sql = 'SELECT `Id`,`Title`,`Content`, UNIX_TIMESTAMP(`Time`) AS `Time` FROM `NotifyLog`'.
152 ' ORDER BY `Time` DESC LIMIT '.$Count;
153 $DbResult = $this->System->Database->query($sql);
154 while ($Line = $DbResult->fetch_assoc())
155 {
156 $Items[] = array
157 (
158 'Title' => $Line['Title'],
159 'Link' => 'https://'.$this->System->Config['Web']['Host'].$this->System->Link('/notify/?i='.$Line['Id']),
160 'Description' => $Line['Content'],
161 'Time' => $Line['Time'],
162 );
163 }
164
165 $RSS = new RSS();
166 $RSS->Title = $this->System->Config['Web']['Title'].' - Záznamy upozornění';
167 $RSS->Link = 'https://'.$this->System->Config['Web']['Host'].'/';
168 $RSS->Description = 'Záznam upozornění '.$this->System->Config['Web']['Description'];
169 $RSS->WebmasterEmail = $this->System->Config['Web']['AdminEmail'];
170 $RSS->Items = $Items;
171 return $RSS->Generate();
172 }
173
174 static function Cast(Module $Module): ModuleNotify
175 {
176 if ($Module instanceof ModuleNotify)
177 {
178 return $Module;
179 }
180 throw new Exception('Expected ModuleNotify type but got '.gettype($Module));
181 }
182}
183
184class PageNotify extends Page
185{
186 function __construct(System $System)
187 {
188 parent::__construct($System);
189 $this->Title = 'Upozornění';
190 $this->Description = 'Upozornění';
191 $this->ParentClass = 'PagePortal';
192 }
193
194 function Show(): string
195 {
196 if (!ModuleUser::Cast($this->System->GetModule('User'))->User->CheckPermission('Notify', 'Show'))
197 return 'Nemáte oprávnění';
198
199 $Output = '<style>
200 table { border-collapse: collapse; }
201 table, th, td { border: 1px solid gray; }
202 td { padding: 5px; }
203 </style>';
204 if (!array_key_exists('i', $_GET) or !is_numeric($_GET['i'])) return 'Položka nenalezena';
205 $Id = $_GET['i'] * 1;
206 $DbResult = $this->Database->select('NotifyLog', 'Title,Content, UNIX_TIMESTAMP(`Time`) AS `Time`', 'Id='.$Id);
207 if ($DbResult->num_rows > 0)
208 {
209 $DbRow = $DbResult->fetch_assoc();
210 $Output .= '<h3>'.$DbRow['Title'].'</h3>'.
211 '<div>Čas: '.TimeToMysqlDateTime($DbRow['Time']).'</div>'.
212 '<p>'.$DbRow['Content'].'</p>';
213 } else $Output = 'Položka nenalezena';
214 return $Output;
215 }
216}
217
218class NotifyCategory extends Model
219{
220 static function GetModelDesc(): ModelDesc
221 {
222 $Desc = new ModelDesc(self::GetClassName());
223 $Desc->AddString('Name');
224 $Desc->AddString('SysName');
225 return $Desc;
226 }
227}
228
229class NotifyUser extends Model
230{
231 static function GetModelDesc(): ModelDesc
232 {
233 $Desc = new ModelDesc(self::GetClassName());
234 $Desc->AddReference('User', User::GetClassName());
235 $Desc->AddReference('Contact', Contact::GetClassName());
236 $Desc->AddInteger('Period');
237 return $Desc;
238 }
239}
Note: See TracBrowser for help on using the repository browser.