source: trunk/Modules/Log/Log.php

Last change on this file was 893, checked in by chronos, 21 months ago
  • Fixed: Class types casting for better type checking.
  • Fixed: XML direct export.
  • Modified: User class instance moved from Core class to ModuleUser class.
File size: 9.6 KB
Line 
1<?php
2
3class ModuleLog extends Module
4{
5 var $Excludes;
6
7 function __construct(System $System)
8 {
9 parent::__construct($System);
10 $this->Name = 'Log';
11 $this->Version = '1.0';
12 $this->Creator = 'Chronos';
13 $this->License = 'GNU/GPL';
14 $this->Description = 'Log various application events';
15 $this->Dependencies = array('Error', 'News', 'Translation');
16
17 $this->Excludes = array();
18 }
19
20 function DoStart(): void
21 {
22 $this->System->RegisterPage(['log'], 'PageLog');
23 $this->System->ModuleManager->Modules['Error']->OnError[] = array($this, 'DoAddItem');
24 $this->System->ModuleManager->Modules['News']->RegisterRSS(array('Title' => T('Logs'),
25 'Channel' => 'log', 'Callback' => array('PageLog', 'ShowRSS'), 'Permission' => LICENCE_ADMIN));
26 }
27
28 function DoAddItem($Message)
29 {
30 $this->WriteLog($Message, LOG_TYPE_ERROR);
31 }
32
33 function WriteLog($Text, $Type)
34 {
35 $User = ModuleUser::Cast($this->System->GetModule('User'))->User;
36 if (isset($User) and !is_null($User->Id))
37 $UserId = $User->Id;
38 else $UserId = 'NULL';
39 $Query = 'INSERT INTO `Log` ( `User` , `Type` , `Text` , `Date` , `IP`, `URL` ) '.
40 'VALUES ('.$UserId.', '.$Type.', "'.addslashes($Text).'", NOW(), "'.
41 GetRemoteAddress().'", "'.GetRequestURI().'")';
42 $this->System->Database->query($Query);
43 }
44
45 static function Cast(Module $Module): ModuleLog
46 {
47 if ($Module instanceof ModuleLog)
48 {
49 return $Module;
50 }
51 throw new Exception('Expected '.ModuleLog::GetClassName().' type but got '.gettype($Module));
52 }
53}
54
55// Log types
56define('LOG_TYPE_TRANSLATION', 1);
57define('LOG_TYPE_DOWNLOAD', 2);
58define('LOG_TYPE_USER', 3);
59define('LOG_TYPE_MODERATOR', 4);
60define('LOG_TYPE_ERROR', 10);
61define('LOG_TYPE_IMPORT', 11);
62define('LOG_TYPE_EXPORT', 12);
63define('LOG_TYPE_CZWOW', 13);
64define('LOG_TYPE_ADMINISTRATION', 14);
65define('LOG_TYPE_PAGE_NOT_FOUND', 15);
66
67// TODO: Change global function to module class local method
68function WriteLog($Text, $Type)
69{
70 global $System, $User;
71
72 if (isset($User) and !is_null($User->Id)) $UserId = $User->Id;
73 else $UserId = 'NULL';
74 $Query = 'INSERT INTO `Log` ( `User` , `Type` , `Text` , `Date` , `IP`, `URL` ) '.
75 'VALUES ('.$UserId.', '.$Type.', "'.addslashes($Text).'", NOW(), "'.
76 GetRemoteAddress().'", "'.GetRequestURI().'")';
77 $System->Database->query($Query);
78}
79
80class PageLog extends Page
81{
82 function ShowRSS()
83 {
84 $this->RawPage = true;
85 $Output = '';
86 $Items = array();
87 if (array_key_exists('type', $_GET)) $Where = ' WHERE `Type` = "'.($_GET['type'] * 1).'"';
88 else $Where = '';
89 $sql = 'SELECT *, UNIX_TIMESTAMP(`Date`) AS `TimeCreate`, (SELECT `User`.`Name` FROM `User` WHERE `User`.`ID` = `Log`.`User`) AS `UserName`, `Date` FROM `Log`'.
90 $Where.' ORDER BY `Date` DESC LIMIT 100';
91 $DbResult = $this->System->Database->query($sql);
92 while ($Line = $DbResult->fetch_assoc())
93 {
94 $DbResult2 = $this->System->Database->query('SELECT * FROM `LogType` WHERE `Id`='.$Line['Type']);
95 $LogType = $DbResult2->fetch_assoc();
96
97 if ($Line['Type'] == LOG_TYPE_ERROR) $Line['Text'] = htmlspecialchars($Line['Text']);
98 $Line['Text'] = str_replace("\n", '<br>', $Line['Text']);
99
100 $Items[] = array
101 (
102 'Title' => $LogType['Name'].' ('.$Line['UserName'].', '.$Line['IP'].')',
103 'Link' => 'https://'.Core::Cast($this->System)->Config['Web']['Host'].$this->System->Link('/log/'),
104 'Description' => $LogType['Name'].': '.$Line['Text'].' ('.$Line['UserName'].
105 ', '.$Line['IP'].', '.HumanDate($Line['Date']).')',
106 'Time' => $Line['TimeCreate'],
107 );
108 }
109
110 $Output .= GenerateRSS(array
111 (
112 'Title' => Core::Cast($this->System)->Config['Web']['Title'].' - '.T('Logs'),
113 'Link' => 'https://'.Core::Cast($this->System)->Config['Web']['Host'].$this->System->Link('/'),
114 'Description' => Core::Cast($this->System)->Config['Web']['Description'],
115 'WebmasterEmail' => Core::Cast($this->System)->Config['Web']['AdminEmail'],
116 'Items' => $Items,
117 ));
118 return $Output;
119 }
120
121 function Show(): string
122 {
123 if (array_key_exists('a', $_POST)) $Action = $_POST['a'];
124 else if (array_key_exists('a', $_GET)) $Action = $_GET['a'];
125 else $Action = '';
126 if ($Action == 'delerrlog') $Output = $this->DeleteErrorLog();
127 else $Output = $this->ShowList();
128 return $Output;
129 }
130
131 function ShowList()
132 {
133 $User = ModuleUser::Cast($this->System->GetModule('User'))->User;
134 $TranslationTree = $this->System->ModuleManager->Modules['Translation']->GetTranslationTree();
135
136 $this->Title = T('System log');
137 $Output = '';
138 if (array_key_exists('type', $_GET))
139 {
140 if (is_numeric($_GET['type'])) $_SESSION['type'] = $_GET['type'] * 1;
141 else $_SESSION['type'] = '';
142 } else if (!array_key_exists('type', $_SESSION)) $_SESSION['type'] = '';
143
144 if (array_key_exists('group', $_GET)) $_SESSION['group'] = $_GET['group'];
145
146 if ($_SESSION['type'] != '') $WhereType = ' (`Type`='.$_SESSION['type'].')';
147 else $WhereType = '1=1';
148
149 $RSSChannels = array(
150 array('Title' => 'Záznamy změn', 'Channel' => 'log&amp;type='.$_SESSION['type'])
151 );
152
153 // Show category filter
154 if ($User->Licence(LICENCE_MODERATOR))
155 {
156 $Output = '<strong>'.T('Filter').':</strong>';
157 $Item = '<a href="'.$this->System->Link('/log/?type=').'" title="Bez filtrování">'.T('All').'</a>';
158 if ($_SESSION['type'] == '') $Item = '<strong>'.$Item.'</strong>';
159 $Output .= ' '.$Item;
160 $DbResult = $this->System->Database->query('SELECT * FROM `LogType`');
161 while ($LogType = $DbResult->fetch_assoc())
162 {
163 $Item = '<a href="'.$this->System->Link('/log/?type='.$LogType['Id']).'" style="color:'.
164 $LogType['Color'].'" title="'.$LogType['Name'].'">'.T($LogType['Name']).'</a>';
165 if ($_SESSION['type'] == $LogType['Id']) $Item = '<strong>'.$Item.'</strong>';
166 $Output .= ' '.$Item;
167 }
168 // echo ' Formát: datum: text zprávy (uživatel, IP)<br /><br />';
169 $Output .= '<br /><br />';
170
171 if (array_key_exists('type', $_SESSION)) $Where = ' WHERE '.$WhereType;
172 else
173 {
174 if (array_key_exists('group', $_SESSION)) $Where = ' WHERE `Text` LIKE "%'.$TranslationTree[$_SESSION['group']]['Name'].'%"';
175 else $Where = '';
176 }
177 //if (($Where != '') and (array_key_exists('group', $_SESSION))) $Where .= ' AND text LIKE "%'.$TranslationTree[$_SESSION['group']]['Name'].'%"';
178
179 $DbResult = $this->System->Database->query('SELECT COUNT(*) FROM `Log` '.$Where);
180 $DbRow = $DbResult->fetch_row();
181 $PageList = GetPageList($DbRow[0]);
182
183 $Output .= $PageList['Output'];
184
185 $TableColumns = array(
186 array('Name' => 'Date', 'Title' => T('Time')),
187 );
188 if ($_SESSION['type'] == '') $TableColumns[] =
189 array('Name' => 'LogName', 'Title' => T('Type'));
190 $TableColumns = array_merge($TableColumns, array(
191 array('Name' => 'Text', 'Title' => T('Content')),
192 array('Name' => 'UserName', 'Title' => T('User')),
193 array('Name' => 'IP', 'Title' => T('Address')),
194 array('Name' => 'URL', 'Title' => T('URL')),
195 ));
196 $Order = GetOrderTableHeader($TableColumns, 'date', 1);
197 $Output .= '<table width="98%" class="BaseTable">'.
198 $Order['Output'];
199
200 $sql = 'SELECT *, `LogType`.`Color` AS `LogColor`, `LogType`.`Name` AS `LogName`, '.
201 '(SELECT `User`.`Name` FROM `User` WHERE `User`.`ID` = `Log`.`User`) AS `UserName` FROM `Log` LEFT JOIN `LogType` ON `LogType`.`Id`=`Log`.`Type` '.$Where.$Order['SQL'].$PageList['SQLLimit'];
202 $DbResult = $this->System->Database->query($sql);
203 while ($Line = $DbResult->fetch_assoc())
204 {
205 if ($Line['Type'] == LOG_TYPE_ERROR) $Line['Text'] = htmlspecialchars($Line['Text']);
206 $Line['Text'] = str_replace("\n", '<br/>', $Line['Text']);
207 $Output .= '<tr><td>'.$Line['Date'].'</td>';
208 if ($_SESSION['type'] == '') $Output .= '<td>'.T($Line['LogName']).'</td>';
209 $Output .= '<td><span style="color: '.$Line['LogColor'].'">'.$Line['Text'].'</span></td>'.
210 '<td><a href="'.$this->System->Link('/user/?user='.$Line['User']).'">'.$Line['UserName'].'</a></td>'.
211 '<td>'.$Line['IP'].'</td>'.
212 '<td>'.$Line['URL'].'</td></tr>';
213 }
214 $Output .= '</table>'.
215 $PageList['Output'];
216 if ($User->Licence(LICENCE_ADMIN))
217 {
218 $Output .= '<div>'.T('Remove').': <a href="'.$this->System->Link('/log/?a=delerrlog&amp;type='.LOG_TYPE_ERROR).'">'.T('Error logs').'</a> '.
219 '<a href="'.$this->System->Link('/log/?a=delerrlog&amp;type='.LOG_TYPE_PAGE_NOT_FOUND).'">'.T('Missing').'</a></div>';
220 }
221 } else $Output .= ShowMessage(T('Access denied'), MESSAGE_CRITICAL);
222
223 return $Output;
224 }
225
226 function DeleteErrorLog()
227 {
228 $User = ModuleUser::Cast($this->System->GetModule('User'))->User;
229 if ($User->Licence(LICENCE_ADMIN) and
230 (($_GET['type'] == LOG_TYPE_ERROR) or ($_GET['type'] == LOG_TYPE_PAGE_NOT_FOUND)))
231 {
232 $DbResult = $this->System->Database->select('LogType', '*', 'Id='.$_GET['type']);
233 $LogType = $DbResult->fetch_assoc();
234 $DbResult = $this->System->Database->query('SELECT COUNT(*) FROM `Log` WHERE `Type`='.$_GET['type']);
235 $DbRow = $DbResult->fetch_row();
236 $this->System->Database->query('DELETE FROM `Log` WHERE `Type`='.$_GET['type']);
237 $this->System->ModuleManager->Modules['Log']->WriteLog('Vymazáno záznamů z '.$LogType['Description'].'.', LOG_TYPE_ADMINISTRATION);
238 $Output = ShowMessage('Smazáno všech '.$DbRow[0].' záznamů z '.$LogType['Description'].'.');
239 $Output .= $this->ShowList();
240 return $Output;
241 } else $Output = ShowMessage(T('Access denied'), MESSAGE_CRITICAL);
242 }
243}
Note: See TracBrowser for help on using the repository browser.