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