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