[ Index ]

PHP Cross Reference of Eventum

title

Body

[close]

/include/ -> class.history.php (source)

   1  <?php
   2  /* vim: set expandtab tabstop=4 shiftwidth=4 encoding=utf-8: */
   3  // +----------------------------------------------------------------------+
   4  // | Eventum - Issue Tracking System                                      |
   5  // +----------------------------------------------------------------------+
   6  // | Copyright (c) 2003, 2004, 2005, 2006, 2007 MySQL AB                  |
   7  // |                                                                      |
   8  // | This program is free software; you can redistribute it and/or modify |
   9  // | it under the terms of the GNU General Public License as published by |
  10  // | the Free Software Foundation; either version 2 of the License, or    |
  11  // | (at your option) any later version.                                  |
  12  // |                                                                      |
  13  // | This program is distributed in the hope that it will be useful,      |
  14  // | but WITHOUT ANY WARRANTY; without even the implied warranty of       |
  15  // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        |
  16  // | GNU General Public License for more details.                         |
  17  // |                                                                      |
  18  // | You should have received a copy of the GNU General Public License    |
  19  // | along with this program; if not, write to:                           |
  20  // |                                                                      |
  21  // | Free Software Foundation, Inc.                                       |
  22  // | 59 Temple Place - Suite 330                                          |
  23  // | Boston, MA 02111-1307, USA.                                          |
  24  // +----------------------------------------------------------------------+
  25  // | Authors: João Prado Maia <jpm@mysql.com>                             |
  26  // +----------------------------------------------------------------------+
  27  //
  28  // @(#) $Id: class.history.php 3394 2007-11-04 08:33:06Z balsdorf $
  29  //
  30  
  31  require_once (APP_INC_PATH . "class.error_handler.php");
  32  require_once (APP_INC_PATH . "class.misc.php");
  33  require_once (APP_INC_PATH . "class.mime_helper.php");
  34  require_once (APP_INC_PATH . "class.date.php");
  35  
  36  /**
  37   * Class to handle the business logic related to the history information for
  38   * the issues entered in the system.
  39   *
  40   * @version 1.0
  41   * @author João Prado Maia <jpm@mysql.com>
  42   */
  43  
  44  class History
  45  {
  46      /**
  47       * Method used to format the changes done to an issue.
  48       *
  49       * @access  public
  50       * @param   string $old_value The old value for a specific issue parameter
  51       * @param   string $new_value The new value for a specific issue parameter
  52       * @return  string The formatted string
  53       */
  54      function formatChanges($old_value, $new_value)
  55      {
  56          if (empty($old_value)) {
  57              return 'no value set -> ' . $new_value;
  58          } elseif (empty($new_value)) {
  59              return $old_value . ' -> no value set';
  60          } else {
  61              return $old_value . ' -> ' . $new_value;
  62          }
  63      }
  64  
  65  
  66      /**
  67       * Method used to log the changes made against a specific issue.
  68       *
  69       * @access  public
  70       * @param   integer $iss_id The issue ID
  71       * @param   integer $usr_id The ID of the user.
  72       * @param   integer $htt_id The type ID of this history event.
  73       * @param   string $summary The summary of the changes
  74       * @param   boolean $hide If this history item should be hidden.
  75       * @return  void
  76       */
  77      function add($iss_id, $usr_id, $htt_id, $summary, $hide = false)
  78      {
  79          $stmt = "INSERT INTO
  80                      " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "issue_history
  81                   (
  82                      his_iss_id,
  83                      his_usr_id,
  84                      his_created_date,
  85                      his_summary,
  86                      his_htt_id";
  87          if ($hide == true) {
  88              $stmt .= ", his_is_hidden";
  89          }
  90          $stmt .= ") VALUES (
  91                      " . Misc::escapeInteger($iss_id) . ",
  92                      " . Misc::escapeInteger($usr_id) . ",
  93                      '" . Date_API::getCurrentDateGMT() . "',
  94                      '" . Misc::escapeString($summary) . "',
  95                      $htt_id";
  96          if ($hide == true) {
  97              $stmt .= ", 1";
  98          }
  99          $stmt .= ")";
 100          $res = $GLOBALS["db_api"]->dbh->query($stmt);
 101          if (PEAR::isError($res)) {
 102              Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__);
 103              return -1;
 104          }
 105      }
 106  
 107  
 108      /**
 109       * Method used to get the list of changes made against a specific issue.
 110       *
 111       * @access  public
 112       * @param   integer $iss_id The issue ID
 113       * @param   string $order_by The order to sort the history
 114       * @return  array The list of changes
 115       */
 116      function getListing($iss_id, $order_by = 'DESC')
 117      {
 118          $stmt = "SELECT
 119                      *
 120                   FROM
 121                      " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "issue_history,
 122                      " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "history_type
 123                   WHERE
 124                      htt_id = his_htt_id AND
 125                      his_is_hidden != 1 AND
 126                      his_iss_id=" . Misc::escapeInteger($iss_id) . " AND
 127                      htt_role <= " . Auth::getCurrentRole() . "
 128                   ORDER BY
 129                      his_id $order_by";
 130          $res = $GLOBALS["db_api"]->dbh->getAll($stmt, DB_FETCHMODE_ASSOC);
 131          if (PEAR::isError($res)) {
 132              Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__);
 133              return "";
 134          } else {
 135              for ($i = 0; $i < count($res); $i++) {
 136                  $res[$i]["his_created_date"] = Date_API::getFormattedDate($res[$i]["his_created_date"]);
 137                  $res[$i]["his_summary"] = Mime_Helper::fixEncoding($res[$i]["his_summary"]);
 138              }
 139              return $res;
 140          }
 141      }
 142  
 143  
 144      /**
 145       * Method used to remove all history entries associated with a
 146       * given set of issues.
 147       *
 148       * @access  public
 149       * @param   array $ids The array of issue IDs
 150       * @return  boolean
 151       */
 152      function removeByIssues($ids)
 153      {
 154          $items = implode(", ", $ids);
 155          $stmt = "DELETE FROM
 156                      " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "issue_history
 157                   WHERE
 158                      his_iss_id IN ($items)";
 159          $res = $GLOBALS["db_api"]->dbh->query($stmt);
 160          if (PEAR::isError($res)) {
 161              Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__);
 162              return false;
 163          } else {
 164              return true;
 165          }
 166      }
 167  
 168  
 169      /**
 170       * Returns the id for the history type based on name.
 171       *
 172       * @access  public
 173       * @param   string The name of the history type
 174       * @return  integer The id of this type.
 175       */
 176      function getTypeID($name)
 177      {
 178          static $returns;
 179  
 180  
 181          $serialized = serialize($name);
 182          if (!empty($returns[$serialized])) {
 183              return $returns[$serialized];
 184          }
 185  
 186          if (!is_array($name)) {
 187              $name = array($name);
 188          }
 189  
 190          $stmt = "SELECT
 191                      htt_id
 192                   FROM
 193                      " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "history_type
 194                   WHERE
 195                      htt_name IN('" . join("','", $name) . "')";
 196          $res = $GLOBALS["db_api"]->dbh->getCol($stmt);
 197          if (PEAR::isError($res)) {
 198              Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__);
 199              return "unknown";
 200          } else {
 201              if (count($name) == 1) {
 202                  $res = current($res);
 203              }
 204              $returns[$serialized] = $res;
 205              return $res;
 206          }
 207      }
 208  
 209  
 210      /**
 211       * Returns a list of issues touched by the specified user in the specified time frame.
 212       *
 213       * @access  public
 214       * @param   integer $usr_id The id of the user.
 215       * @param   date $start The start date
 216       * @param   date $end The end date
 217       * @param   date $separate_closed If closed issues should be included in a separate array
 218       * @param   array $htt_exclude Addtional History Types to ignore
 219       * @return  array An array of issues touched by the user.
 220       */
 221      function getTouchedIssuesByUser($usr_id, $start, $end, $separate_closed = false, $htt_exclude = array())
 222      {
 223  
 224          $htt_list = History::getTypeID(
 225              array_merge(array(
 226                  'notification_removed',
 227                  'notification_added',
 228                  'notification_updated',
 229                  'remote_replier_added',
 230                  'replier_added',
 231                  'replier_removed',
 232                  'replier_other_added',
 233              ), $htt_exclude)
 234          );
 235  
 236          $stmt = "SELECT
 237                      iss_id,
 238                      iss_prj_id,
 239                      iss_summary,
 240                      iss_customer_id,
 241                      iss_customer_contract_id,
 242                      sta_title,
 243                      pri_title,
 244                      sta_is_closed
 245                   FROM
 246                      " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "issue_history,
 247                      " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "issue
 248                      LEFT JOIN
 249                          " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "status
 250                      ON
 251                          iss_sta_id = sta_id
 252                   LEFT JOIN
 253                      " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "project_priority
 254                   ON
 255                      iss_pri_id = pri_id
 256                   WHERE
 257                      his_iss_id = iss_id AND
 258                      his_usr_id = " . Misc::escapeInteger($usr_id) . " AND
 259                      his_created_date BETWEEN '" . Misc::escapeString($start) . "' AND '" . Misc::escapeString($end) . "' AND
 260                      his_htt_id NOT IN(" . join(',', $htt_list) . ") AND
 261                      iss_prj_id = " . Auth::getCurrentProject() . "
 262                   GROUP BY
 263                      iss_id
 264                   ORDER BY
 265                      iss_id ASC";
 266          $res = $GLOBALS["db_api"]->dbh->getAll($stmt, DB_FETCHMODE_ASSOC);
 267          if (PEAR::isError($res)) {
 268              Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__);
 269              return "";
 270          } else {
 271              $data = array(
 272                  "closed"    =>  array(),
 273                  "other"     =>  array()
 274              );
 275              if (count($res) > 0) {
 276                  if (isset($_POST['show_per_issue'])) {
 277                      Time_Tracking::fillTimeSpentByIssueAndTime($res, $usr_id, $start, $end);
 278                  }
 279                  if (isset($_POST['separate_status_changed'])) {
 280                      History::fillStatusChangedOnlyIssues($res, $usr_id, $start, $end);
 281                  }
 282                  foreach ($res as $index => $row) {
 283                      if ((!empty($row["iss_customer_id"])) && (Customer::hasCustomerIntegration($row['iss_prj_id']))) {
 284                          $details = Customer::getDetails($row["iss_prj_id"], $row["iss_customer_id"], $res['iss_customer_contract_id']);
 285                          $row["customer_name"] = $details["customer_name"];
 286                      }
 287                      if (($separate_closed) && ($row['sta_is_closed'] == 1)) {
 288                          $data['closed'][] = $row;
 289                      } elseif ((isset($_POST['separate_status_changed'])) && $row['only_stat_changed']) {
 290                          $data['status_changed'][] = $row;
 291                      } else {
 292                          $data['other'][] = $row;
 293                      }
 294                  }
 295                  $sort_function = create_function('$a,$b', 'return strcasecmp(@$a["customer_name"], @$b["customer_name"]);');
 296                  @usort($data['closed'], $sort_function);
 297                  @usort($data['other'], $sort_function);
 298              }
 299          }
 300          return $data;
 301      }
 302  
 303  
 304      /**
 305       * Returns the number of issues for the specified user that are currently set to the specified status(es).
 306       *
 307       * @access  public
 308       * @param   integer $usr_id The id of the user.
 309       * @param   date $start The start date
 310       * @param   date $end The end date
 311       * @param   array $statuses An array of status abreviations to return counts for.
 312       * @return  array An array containing the number of issues for the user set tothe specified statuses.
 313       */
 314      function getTouchedIssueCountByStatus($usr_id, $start, $end, $statuses = false)
 315      {
 316          $stmt = "SELECT
 317                      sta_title,
 318                      count(DISTINCT iss_id) as total
 319                   FROM
 320                      " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "issue,
 321                      " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "status,
 322                      " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "issue_history
 323                   WHERE
 324                      his_iss_id = iss_id AND
 325                      iss_sta_id = sta_id AND
 326                      iss_prj_id = " . Auth::getCurrentProject() . " AND
 327                      his_usr_id = " . Misc::escapeInteger($usr_id) . " AND
 328                      his_created_date BETWEEN '" . Misc::escapeString($start) . "' AND '" . Misc::escapeString($end) . "'";
 329          if ($statuses != false) {
 330              $stmt .= " AND
 331                      (
 332                          sta_abbreviation IN('" . join("','", $statuses) . "') OR
 333                          sta_is_closed = 1
 334                      )";
 335          }
 336          $stmt .= "
 337                   GROUP BY
 338                      sta_title
 339                   ORDER BY
 340                      sta_rank";
 341          $res = $GLOBALS["db_api"]->dbh->getAll($stmt, DB_FETCHMODE_ASSOC);
 342          if (PEAR::isError($res)) {
 343              Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__);
 344              return array();
 345          } else {
 346              return $res;
 347          }
 348      }
 349  
 350  
 351      /**
 352       * Returns the history for a specified user in a specified time frame for an optional type
 353       *
 354       * @access  public
 355       * @param   integer $usr_id The id of the user.
 356       * @param   date $start The start date
 357       * @param   date $end The end date
 358       * @param   array $htt_id The htt_id or id's to to return history for.
 359       * @return  array An array of history items
 360       */
 361      function getHistoryByUser($usr_id, $start, $end, $htt_id = false)
 362      {
 363          $stmt = "SELECT
 364                      his_id,
 365                      his_iss_id,
 366                      his_created_date,
 367                      his_summary,
 368                      his_htt_id
 369                   FROM
 370                      " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "issue_history
 371                   WHERE
 372                      his_usr_id = " . Misc::escapeInteger($usr_id) . " AND
 373                      his_created_date BETWEEN '" . date("Y/m/d", $start) . "' AND '" . date("Y/m/d", $end) . "'";
 374          if ($htt_id != false) {
 375              $stmt .= "
 376                      AND his_htt_id IN(" . join(",", Misc::escapeInteger($htt_id)) . ")";
 377          }
 378          $res = $GLOBALS["db_api"]->dbh->getAll($stmt, DB_FETCHMODE_ASSOC);
 379          if (PEAR::isError($res)) {
 380              Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__);
 381              return array();
 382          }
 383          return $res;
 384      }
 385  
 386  
 387      /**
 388       * Returns the last person to close the issue
 389       *
 390       * @param   integer $issue_id The ID of the issue
 391       * @return  integer usr_id
 392       */
 393      function getIssueCloser($issue_id)
 394      {
 395          $sql = "SELECT
 396                      his_usr_id
 397                  FROM
 398                      " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "issue_history
 399                  WHERE
 400                      his_iss_id = " . Misc::escapeInteger($issue_id) . " AND
 401                      his_htt_id = '" . History::getTypeID('issue_closed') . "'
 402                  ORDER BY
 403                      his_created_date DESC
 404                  LIMIT 1";
 405          $res = $GLOBALS["db_api"]->dbh->getOne($sql);
 406          if (PEAR::isError($res)) {
 407              Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__);
 408              return 0;
 409          }
 410          return $res;
 411      }
 412  
 413      /**
 414       * Fills a result set with a flag indicating if this issue only had it's status
 415       * changed in the given time period.
 416       *
 417       * @access  public
 418       * @param   array $res User issues
 419       * @param   integer $usr_id The ID of the user this report is for.
 420       * @param   integer $start The timestamp of the beginning of the report.
 421       * @param   integer $end The timestamp of the end of this report.
 422       * @return  boolean True if only status changed else false
 423       */
 424      function fillStatusChangedOnlyIssues(&$res, $usr_id, $start, $end) {
 425  
 426          $issue_ids = array();
 427          for ($i = 0; $i < count($res); $i++) {
 428              $issue_ids[] = Misc::escapeInteger($res[$i]["iss_id"]);
 429          }
 430          $ids = implode(", ", $issue_ids);
 431  
 432          $sql = "SELECT
 433                      " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "issue_history.his_iss_id,
 434                      " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "issue_history.his_htt_id
 435                   FROM
 436                      " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "issue_history
 437                   WHERE
 438                      " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "issue_history.his_htt_id != " . History::getTypeID('status_changed') . " AND
 439                      " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "issue_history.his_htt_id != " . History::getTypeID('issue_updated') . " AND
 440                      " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "issue_history.his_iss_id IN (" . $ids . ") AND
 441                      " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "issue_history.his_usr_id = " . Misc::escapeInteger($usr_id) . " AND
 442                      " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "issue_history.his_created_date BETWEEN '" . Misc::escapeString($start) . "' AND '" . Misc::escapeString($end) . "'
 443                  GROUP BY his_iss_id";
 444  
 445          $result = $GLOBALS["db_api"]->dbh->getAssoc($sql);
 446          if (PEAR::isError($result)) {
 447              Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__);
 448          } else {
 449              foreach($res as $key => $item) {
 450                  @$res[$key]['only_stat_changed'] = (array_key_exists($item['iss_id'], $result) ? false : true);
 451              }
 452          }
 453      }
 454  }
 455  
 456  // benchmarking the included file (aka setup time)
 457  if (APP_BENCHMARK) {
 458      $GLOBALS['bench']->setMarker('Included History Class');
 459  }


Generated: Wed Dec 19 21:21:33 2007 Cross-referenced by PHPXref 0.7