config migration in source code; config page is not needed anymore
[iserv-mod-error-reporter.git] / inc / class_erErrorReportManager.inc
1 <?php
2 /**
3 * @file class_erErrorReportManager.inc -- management of multiple error reports
4 * @author Roland Hieber (roland.hieber@wilhelm-gym.net)
5 * @date 18.10.2007
6 *
7 * Copyright © 2007 Roland Hieber
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 * THE SOFTWARE.
26 */
27
28 require_once("mod_error-reporter/class_erErrorReport.inc");
29 require_once("mod_error-reporter/class_erConfig.inc");
30 require_once("mod_error-reporter/functions.inc");
31 require_once("cfg.inc");
32 require_once("db.inc");
33 require_once("user.inc");
34
35 db_query("SET DATESTYLE = ISO ");
36
37 /**
38 * @page errorreportmanager_constants erErrorReportManager Constants
39 * @section errorreportmanager_sorting Sorting constants
40 * - @b ER_ERM_SORT_UID: Array is sorted by unique ID
41 * - @b ER_ERM_SORT_DATE: Array is sorted by the creation date
42 * - @b ER_ERM_SORT_OWNER: Array is sorted by owner of the error report
43 * - @b ER_ERM_SORT_MACHINE: Array is sorted by the machine to which the
44 * report refers
45 * - @b ER_ERM_SORT_TEXT: Array is sorted by text / notes
46 * - @b ER_ERM_SORT_COMMENT: Array is sorted by comment
47 * - @b ER_ERM_SORT_COMMENTOWNER: Array is sorted by the account name of the
48 * person who wrote the comment
49 * - @b ER_ERM_SORT_VISIBILITY: Array is sorted by hide status
50 * @section errorreportmanager_sorting_dir Sorting direction constants
51 * - @b ER_ERM_SORT_ASC: Array is sorted in ascending order
52 * - @b ER_ERM_SORT_DESC: Array is sorted in descending order
53 */
54 define("ER_ERM_SORT_UID", 0); /*< sort by unique ID */
55 define("ER_ERM_SORT_DATE", 1); /*< sort by date */
56 define("ER_ERM_SORT_OWNER", 2); /*< sort by owner */
57 define("ER_ERM_SORT_MACHINE", 3); /*< sort by machine to which the */
58 /*< report refers */
59 define("ER_ERM_SORT_TEXT", 4); /*< sort by text*/
60 define("ER_ERM_SORT_COMMENT", 5); /*< sort by comment */
61 define("ER_ERM_SORT_COMMENTOWNER", 6); /*< sort by account name of the */
62 /*< person who wrote the comment */
63 define("ER_ERM_SORT_VISIBILITY", 6); /*< sort by visibility */
64
65 define("ER_ERM_SORT_ASC", 0); /*< sort ascending */
66 define("ER_ERM_SORT_DESC", 1); /*< sort descending */
67
68 /**
69 * Management of error reports
70 *
71 * This class allows a comprehensive management of error reports.
72 *
73 * @par Error reports management
74 * To add an error reports, simply create an instance of this class and call
75 * writeErrorReport() with an erErrorReport object as the only parameter. If
76 * the $nUid member of the erErrorReport object is <tt>null</tt>,
77 * writeErrorReport() will use the next ID which is not used in the table.
78 *
79 * @par
80 * An error report that has been written to the database can be changed using
81 * writeErrorReport(), setting the $nUid member of the erErrorReport parameter
82 * to the UID of the error report to be changed.
83 *
84 * @par
85 * To change the visibility of an error report to @e hidden, call
86 * setErrorReportDoneFlag() with the UID of the error report and set the second
87 * parameter to <tt>false</tt>.
88 *
89 * @par
90 * To delete an error report from the database, call deleteErrorReport() with
91 * the UID of the error report you want to delete.
92 *
93 * @par
94 * Error reports can be retrieved by their UID (getErrorReportByID()), by
95 * creation date (getErrorReportsByDate()), by owner (getErrorReportsByOwner()),
96 * by machine to which the report refers (getErrorReportsByMachine()) and by
97 * the person who wrote the comment (getErrorReportsByCommentOwner()). All
98 * error reports in the database can be retrieved using getErrorReports(). All
99 * of these functions return a object of type erErrorReport or an array of
100 * erErrorReport objects.
101 *
102 * @par Example
103 * The following example creates a new error report “This doesn’t work”, written
104 * by the user “testuser” on February 5, 2007, which refers to the machine
105 * “Client-26” and is not visible for non-admin users. Then it adds a nice
106 * comment, makes the error report visible and writes it to the database.
107 * @code
108 * <?php
109 * require_once("class_erErrorReportManager.inc");
110 * $obj = new erErrorReportManager;
111 * $em = new erErrorReport(strtotime("2007-02-05"), "testuser", "Client-26",
112 * "This doesn’t work", false);
113 * $em->setComment("We know that already", "admin");
114 * // $em->nUid is null, so writeErrorReport() calculates the UID by itself
115 * $nNewID = $obj->writeErrorReport($em);
116 * @endcode
117 */
118
119 class erErrorReportManager {
120
121 /////////////////////////////////// QUERYING /////////////////////////////////
122
123 /**
124 * @name Quering
125 * @{ */
126
127 /**
128 * Get the number of reported errors
129 * @return int
130 */
131 public function getNumErrorReports() {
132 $ar = pg_fetch_array(db_query("SELECT COUNT(*) AS count FROM ".
133 "mod_errorreporter;"), 0);
134 return intval($ar["count"]);
135 }
136
137 /**
138 * Get all error reports in the database.
139 * If this function fails, it returns <tt>null</tt>. Call getLastError() to
140 * get more information.
141 * @param $arcSort (array of constants) Defines the sorting of the returned
142 * array. See the documentation of the $arcSort parameter of
143 * buildOrderByClause() for more information.
144 * @return array of objects of type erErrorReport
145 */
146 public function getErrorReports($arcSort = array(ER_ERM_SORT_UID =>
147 ER_ERM_SORT_ASC)) {
148 return $this->readFromSQL("", $arcSort);
149 }
150
151 /**
152 * Get an error report by its unique ID in database.
153 * If this function fails, it returns <tt>null</tt>.
154 * @param $nID (int) ID of the error report
155 * @return erErrorReport
156 */
157 public function getErrorReportByID($nID) {
158 $arReturn = $this->readFromSQL("er_uid = ".qdb(intval($nID)));
159 if(is_array($arReturn) and count($arReturn) > 0) {
160 return $arReturn[0]; // return as scalar
161 } else {
162 return null;
163 }
164 }
165
166 /**
167 * Get all error reports which have been created on the specified date.
168 * If this function fails, it returns <tt>null</tt>. Call getLastError() to
169 * get more information.
170 * @param $tsDate (timestamp) Date
171 * @param $arcSort (array of constants) Defines the sorting of the returned
172 * array. See the documentation of the $arcSort parameter of
173 * buildOrderByClause() for more information.
174 * @return array of objects of type erErrorReport
175 */
176 public function getErrorReportsByDate($tsDate, $arcSort =
177 array(ER_ERM_SORT_UID => ER_ERM_SORT_ASC)) {
178 return $this->readFromSQL("er_date = ".qdb(date("Y\-m\-d", $tsDate)), $arcSort);
179 }
180
181 /**
182 * Get all error reports which have been created by the specified user.
183 * If this function fails, it returns <tt>null</tt>. Call getLastError() to
184 * get more information.
185 * @param $strAct (string) Account name
186 * @param $arcSort (array of constants) Defines the sorting of the returned
187 * array. See the documentation of the $arcSort parameter of
188 * buildOrderByClause() for more information.
189 * @return array of objects of type erErrorReport
190 */
191 public function getErrorReportsByOwner($strAct, $arcSort =
192 array(ER_ERM_SORT_UID => ER_ERM_SORT_ASC)) {
193 return $this->readFromSQL("er_act = ".qdb($strAct), $arcSort);
194 }
195
196 /**
197 * Get all error reports which are related to a specified machine.
198 * If this function fails, it returns <tt>null</tt>. Call getLastError() to
199 * get more information.
200 * @param $strMachine (string) Machine name
201 * @param $arcSort (array of constants) Defines the sorting of the returned
202 * array. See the documentation of the $arcSort parameter of
203 * buildOrderByClause() for more information.
204 * @return array of objects of type erErrorReport
205 */
206 public function getErrorReportsByMachine($strMachine,
207 $arcSort = array(ER_ERM_SORT_UID => ER_ERM_SORT_ASC)) {
208 return $this->readFromSQL("er_machine = ".qdb($strMachine), $arcSort);
209 }
210
211 /**
212 * Get all error reports which have been commented by the specified user.
213 * If this function fails, it returns <tt>null</tt>. Call getLastError() to
214 * get more information.
215 * @param $strAct (string) Account name
216 * @param $arcSort (array of constants) Defines the sorting of the returned
217 * array. See the documentation of the $arcSort parameter of
218 * buildOrderByClause() for more information.
219 * @return array of objects of type erErrorReport
220 */
221 public function getErrorReportsByCommentOwner($strAct,
222 $arcSort = array(ER_ERM_SORT_UID => ER_ERM_SORT_ASC)) {
223 return $this->readFromSQL("er_commentact = ".qdb($strAct), $arcSort);
224 }
225
226 /*@}*/
227
228 /**
229 * Get datasets from the SQL tables.
230 * This function should not be called directly. Use the getBy* functions
231 * instead. If this function fails, it returns <tt>null</tt>. Call
232 * getLastError() to get more information.
233 * @internal
234 * @param $strWhere (string) Parameters for the SQL WHERE clause
235 * @param $arcSort (array of constants) Defines the sorting of the returned
236 * array. See the documentation of the $arcSort parameter of
237 * buildOrderByClause() for more information.
238 * @return array of objects of type erErrorReport
239 */
240 protected function readFromSQL($strWhere = "", $arcSort =
241 array(ER_ERM_SORT_UID => ER_ERM_SORT_ASC)) {
242 $arReturn = array();
243
244 // only allow visible reports for non-admins, but all reports for
245 // admins and owners
246 if(erConfig::userIsAdmin()) {
247 $strWhereClause = (trim($strWhere) == "") ? "" : "WHERE $strWhere";
248 } else {
249 $strWhereClause = "WHERE ".((trim($strWhere) == "") ? "" :
250 "$strWhere AND ").sprintf("((er_act = '%s') or (er_hidden IS NULL OR ".
251 " NOT er_hidden))", $_SESSION["act"]);
252 }
253
254 $strSortClause = $this->buildOrderByClause($arcSort);
255
256 // fetch the error reports
257 $hQuery = db_query("SELECT * FROM mod_errorreporter $strWhereClause ".
258 "$strSortClause;");
259 if(!is_resource($hQuery)) {
260 setLastError(ER_ERROR_SQL);
261 return null;
262 }
263 while($arResult = pg_fetch_array($hQuery)) {
264 $er = new erErrorReport(strtotime($arResult["er_date"]),
265 $arResult["er_act"], $arResult["er_machine"], $arResult["er_text"],
266 $arResult["er_hidden"] == "t");
267 $er->setUid($arResult["er_uid"]);
268 $er->setComment($arResult["er_comment"], $arResult["er_commentact"]);
269 $arReturn[] = $er;
270 }
271 return $arReturn;
272 }
273
274 /**
275 * Build a ORDER BY clause from an array.
276 * This helper function takes an array of sorting constants as input and
277 * returns an ORDER BY clause. The values in the clause are in the same order
278 * as the constants in the array. The function in the following example
279 * returns an ORDER BY clause where the datasets are first sorted ascending
280 * by visibility, then descending by the machine name to which they refer and
281 * finally ascending by their UID:
282 * @code
283 * $strOrder = buildOrderClause(array(
284 * ER_ERM_SORT_VISIBILITY => ER_ERM_SORT_ASC,
285 * ER_ERM_SORT_MACHINE => ER_ERM_SORT_DESC,
286 * ER_ERM_SORT_UID => ER_ERM_SORT_ASC));
287 * echo $strOrder;
288 * @endcode
289 * The output is: <tt>ORDER BY er_hidden ASC, er_machine DESC, er_uid ASC</tt>
290 * @internal
291 * @param $arcSort (array of constants) The array which declares the order of
292 * the SQL rows. Use @ref errorreportmanager_sorting as keys and
293 * @ref errorreportmanager_sorting_dir as values.
294 * @return string
295 */
296 protected function buildOrderByClause($arcSort) {
297 // build the sorting clause
298 $arstrSort = array();
299 foreach($arcSort as $cSort => $cDir) {
300 switch($cSort) {
301 case ER_ERM_SORT_UID:
302 $arstrSort[] = "er_uid ".($cDir == ER_ERM_SORT_DESC ? "DESC" : "ASC");
303 break;
304 case ER_ERM_SORT_DATE:
305 $arstrSort[] = "er_date ".($cDir == ER_ERM_SORT_DESC ? "DESC" :
306 "ASC");
307 break;
308 case ER_ERM_SORT_OWNER:
309 $arstrSort[] = "er_act ".($cDir == ER_ERM_SORT_DESC ? "DESC" : "ASC");
310 break;
311 case ER_ERM_SORT_MACHINE:
312 $arstrSort[] = "er_machine ".($cDir == ER_ERM_SORT_DESC ? "DESC" :
313 "ASC");
314 break;
315 case ER_ERM_SORT_TEXT:
316 $arstrSort[] = "er_text ".($cDir == ER_ERM_SORT_DESC ? "DESC" :
317 "ASC");
318 break;
319 case ER_ERM_SORT_COMMENT:
320 $arstrSort[] = "er_comment ".($cDir == ER_ERM_SORT_DESC ? "DESC" :
321 "ASC");
322 break;
323 case ER_ERM_SORT_COMMENTOWNER:
324 $arstrSort[] = "er_commentact ".($cDir == ER_ERM_SORT_DESC ? "DESC" :
325 "ASC");
326 break;
327 case ER_ERM_SORT_VISIBILITY:
328 $arstrSort[] = "er_hidden ".($cDir == ER_ERM_SORT_DESC ? "DESC" :
329 "ASC");
330 break;
331 }
332 }
333 return ("ORDER BY ".join(", ", $arstrSort));
334 }
335
336 ////////////////////////// ERROR MESSAGE MANAGEMENT //////////////////////////
337
338 /**
339 * @name Error report management
340 * @{
341 */
342
343 /**
344 * Insert or update an error report in the database.
345 * When the $nUid member of the $erErrorReport object is <tt>null</tt>, a new
346 * unique ID is assigned and the error report is written to the database.
347 * Otherwise, the record having the respective UID in the table is updated.
348 * @param $er (erErrorReport)
349 * @return (int) The unique ID of the inserted or updated record.
350 * @throws Exception
351 */
352 public function writeErrorReport(erErrorReport $er) {
353 if(!erConfig::userHasAccess() and (!$this->userIsOwner($er->nUid) or
354 ($er->getUid() == null and !(erConfig::userIsAdmin())))) {
355 throw new Exception(ER_ERROR_ACCESS_DENIED);
356 }
357
358 $strWhere = null;
359 $strLog = "";
360
361 // Update or insert?
362 $arPut = array();
363 if($er->getUid() == null) {
364 // er_uid is now serial
365 /*$hQuery = db_query("SELECT MAX(er_uid) AS id FROM mod_errorreporter;");
366 if(!is_resource($hQuery)) {
367 setLastError(ER_ERROR_SQL);
368 return -1;
369 }
370 $arResult = pg_fetch_array($hQuery);
371 $er->setUid(intval($arResult["id"]) + 1);*/
372 $strLog = sprintf("Fehlermeldung für Rechner „%s“ eingetragen.",
373 $er->getMachine());
374 } else {
375 $strWhere = "er_uid = ".qdb(intval($er->getUid()));
376 $oOldReport = $this->getErrorReportByID($er->getUid());
377 $strLog = sprintf("Fehlermeldung geändert, Rechner war „%s“, Text war ".
378 "„%s“. Neuer Rechner: „%s“, neuer Text: „%s“, Kommentar: %s",
379 $oOldReport->getMachine(), $oOldReport->getText(), $er->getMachine(),
380 $er->getText(), (strlen($er->getComment()) > 0) ?
381 "„" . $er->getComment() . "“" : "(leer)");
382 }
383 $arPut["er_date"] = date("Y\-m\-d\ G\:i\:s", $er->getDate());
384 $arPut["er_act"] = $er->getOwner();
385 $arPut["er_machine"] = $er->getMachine();
386 $arPut["er_text"] = $er->getText();
387 $arPut["er_comment"] = $er->getComment();
388 $arPut["er_commentact"] = $er->getCommentOwner();
389 $arPut["er_hidden"] = $er->isHidden() ? "true" : "false";
390 db_store("mod_errorreporter", $arPut, $strWhere);
391
392 erInsertLog($strLog);
393
394 // send notification mail, but only if the message is new
395 if(cfg("errorreportermailnotify") and $er->getUid() == null) {
396 $strMailText = sprintf("<html><body>\nEin Benutzer hat eine ".
397 "Fehlermeldung mit dem Fehlermeldungs-Assistenten abgeschickt. ".
398 "Nachfolgend finden sich Angaben über den Fehler.\n".
399 "<table>\n<tr><td>Fehler gemeldet von:</td><td>%s</td></tr>\n".
400 "<tr><td>Datum:</td><td>%s</td></tr>\n".
401 "<tr><td>Betroffener Rechner:</td><td>%s</td></tr>\n".
402 "<tr><td colspan='2'>%s</td></tr>\n</table>\n<hr />\n".
403 "Diese Mail wurde automatisch generiert.\n".
404 "</body></html>", q(erGetRealUserName($er->getOwner())),
405 q(date("d\.m\.Y\ G\:i\:s", $er->getDate())), q($er->getMachine()),
406 q($er->getText()));
407 $strMailSubject = sprintf("%s hat einen Fehler im System gemeldet",
408 q(erGetRealUserName($er->getOwner())));
409 $strMailHeader = sprintf("From: %s <%s>\n".
410 "Content-Type: text/html; charset=utf-8",
411 q(erGetRealUserName($er->getOwner())), user_mail_addr($er->getOwner()));
412 mail(cfg("errorreportermailaddress"), $strMailSubject, $strMailText,
413 $strMailHeader);
414 }
415
416 return $er->getUid();
417 }
418
419 /**
420 * Delete an error report from the database.
421 * @param $nErrorReportID (int) Unique ID of the error report to delete or -1
422 * if an error occured. In this case, call getLastError() to get more
423 * information.
424 */
425 public function deleteErrorReport($nErrorReportID) {
426 if(!(erConfig::userIsAdmin() or $this->userIsOwner($nErrorReportID))) {
427 setLastError(ER_ERROR_ACCESS_DENIED);
428 return -1;
429 }
430
431 $oOldReport = $this->getErrorReportByID($nErrorReportID);
432 db_query(sprintf("DELETE FROM mod_errorreporter WHERE er_uid = '%d';",
433 intval($nErrorReportID)));
434 erInsertLog(sprintf("Fehlermeldung gelöscht, Rechner war „%s“, Text war ".
435 "„%s“", $oOldReport->getMachine(), $oOldReport->getText()));
436 }
437
438 /**
439 * Determine if the current user is the owner of a specified error report.
440 * If this function fails, call getLastError() to get more information.
441 * @param $nID (int) Unique ID of the error report
442 * @return bool
443 */
444 public function userIsOwner($nID) {
445 if(!$_SESSION["act"]) {
446 return false; // user is not logged in
447 } else {
448 $hQuery = db_query(sprintf("SELECT er_act FROM mod_errorreporter WHERE ".
449 "er_uid = %d;", intval($nID)));
450 if(!is_resource($hQuery)) {
451 setLastError(ER_ERROR_SQL);
452 return false;
453 }
454 $arResult = pg_fetch_array($hQuery);
455 return ($arResult["er_act"] == $_SESSION["act"]);
456 }
457 }
458 }
459 ?>
This page took 0.076463 seconds and 5 git commands to generate.