Пример #1
0
 /**
  * Returns the data used by the weekly report.
  *
  * @param string $usr_id The ID of the user this report is for.
  * @param int $prj_id The project id
  * @param string|DateTime $start The start date of this report.
  * @param string|DateTime $end The end date of this report.
  * @param array $options extra options for report:
  * - $separate_closed If closed issues should be separated from other issues.
  * - $ignore_statuses If issue status changes should be ignored in report.
  * - $separate_not_assigned_to_user Separate Issues Not Assigned to User
  * - $show_per_issue Add time spent on issue to issues
  * - $separate_no_time Separate No time spent issues
  * @return array An array of data containing all the elements of the weekly report.
  */
 public static function getWeeklyReport($usr_id, $prj_id, $start, $end, $options = array())
 {
     // figure out timezone
     $user_prefs = Prefs::get($usr_id);
     $tz = $user_prefs['timezone'];
     // if start or end is string, convert assume min and max date are specified
     if (!$start instanceof DateTime) {
         $start = Date_Helper::getDateTime($start, $tz)->setTime(0, 0, 0);
     }
     if (!$end instanceof DateTime) {
         $end = Date_Helper::getDateTime($end, $tz)->setTime(23, 59, 59);
     }
     $start_ts = Date_Helper::getSqlDateTime($start);
     $end_ts = Date_Helper::getSqlDateTime($end);
     $time_tracking = Time_Tracking::getSummaryByUser($usr_id, $prj_id, $start_ts, $end_ts);
     // replace spaces in index with _ and calculate total time
     $total_time = 0;
     foreach ($time_tracking as $category => $data) {
         unset($time_tracking[$category]);
         $time_tracking[str_replace(' ', '_', $category)] = $data;
         $total_time += $data['total_time'];
     }
     // get count of issues assigned in week of report.
     $stmt = 'SELECT
                 COUNT(*)
              FROM
                 {{%issue}},
                 {{%issue_user}},
                 {{%status}}
              WHERE
                 iss_id = isu_iss_id AND
                 iss_sta_id = sta_id AND
                 isu_usr_id = ? AND
                 iss_prj_id = ? AND
                 isu_assigned_date BETWEEN ? AND ?';
     $params = array($usr_id, Auth::getCurrentProject(), $start_ts, $end_ts);
     try {
         $newly_assigned = DB_Helper::getInstance()->getOne($stmt, $params);
     } catch (DbException $e) {
         $newly_assigned = null;
     }
     $email_count = array('associated' => Support::getSentEmailCountByUser($usr_id, $start_ts, $end_ts, true), 'other' => Support::getSentEmailCountByUser($usr_id, $start_ts, $end_ts, false));
     $htt_exclude = array();
     if (!empty($options['ignore_statuses'])) {
         $htt_exclude[] = 'status_changed';
         $htt_exclude[] = 'status_auto_changed';
         $htt_exclude[] = 'remote_status_change';
     }
     $issue_list = History::getTouchedIssuesByUser($usr_id, $prj_id, $start_ts, $end_ts, $htt_exclude);
     $issues = array('no_time' => array(), 'not_mine' => array(), 'closed' => array(), 'other' => array());
     // organize issues into categories
     if ($issue_list) {
         if (!empty($options['show_per_issue']) || !empty($options['separate_no_time'])) {
             Time_Tracking::fillTimeSpentByIssueAndTime($issue_list, $usr_id, $start_ts, $end_ts);
         }
         foreach ($issue_list as $row) {
             if (!empty($row['iss_customer_id']) && CRM::hasCustomerIntegration($row['iss_prj_id'])) {
                 $row['customer_name'] = CRM::getCustomerName($row['iss_prj_id'], $row['iss_customer_id']);
             } else {
                 $row['customer_name'] = null;
             }
             if (!empty($options['separate_closed']) && $row['sta_is_closed'] == 1) {
                 $issues['closed'][] = $row;
             } elseif (!empty($options['separate_not_assigned_to_user']) && !Issue::isAssignedToUser($row['iss_id'], $usr_id)) {
                 $issues['not_mine'][] = $row;
             } elseif (!empty($options['separate_no_time']) && empty($row['it_spent'])) {
                 $issues['no_time'][] = $row;
             } else {
                 $issues['other'][] = $row;
             }
         }
         $sort_function = function ($a, $b) {
             return strcasecmp($a['customer_name'], $b['customer_name']);
         };
         usort($issues['closed'], $sort_function);
         usort($issues['other'], $sort_function);
     }
     return array('start' => $start_ts, 'end' => $end_ts, 'user' => User::getDetails($usr_id), 'group_name' => Group::getName(User::getGroupID($usr_id)), 'issues' => $issues, 'status_counts' => History::getTouchedIssueCountByStatus($usr_id, $prj_id, $start_ts, $end_ts), 'new_assigned_count' => $newly_assigned, 'time_tracking' => $time_tracking, 'email_count' => $email_count, 'phone_count' => Phone_Support::getCountByUser($usr_id, $start_ts, $end_ts), 'note_count' => Note::getCountByUser($usr_id, $start_ts, $end_ts), 'total_time' => Misc::getFormattedTime($total_time, false));
 }
Пример #2
0
 /**
  * Method used to remove all issues associated with a specific list of
  * projects.
  *
  * XXX: this is dangerous, maybe remove such methods?
  *
  * @param   array $ids The list of projects to look for
  * @return  boolean
  */
 public static function removeByProjects($ids)
 {
     $stmt = 'SELECT
                 iss_id
              FROM
                 {{%issue}}
              WHERE
                 iss_prj_id IN (' . DB_Helper::buildList($ids) . ')';
     try {
         $res = DB_Helper::getInstance()->getColumn($stmt, $ids);
     } catch (DbException $e) {
         return false;
     }
     if (count($res) > 0) {
         self::deleteAssociations($res);
         Attachment::removeByIssues($res);
         SCM::removeByIssues($res);
         Impact_Analysis::removeByIssues($res);
         self::deleteUserAssociations($res);
         Note::removeByIssues($res);
         Time_Tracking::removeTimeEntriesByIssues($res);
         Notification::removeByIssues($res);
         Custom_Field::removeByIssues($res);
         Phone_Support::removeByIssues($res);
         History::removeByIssues($res);
         // now really delete the issues
         $items = implode(', ', $res);
         $stmt = "DELETE FROM\n                        {{%issue}}\n                     WHERE\n                        iss_id IN ({$items})";
         DB_Helper::getInstance()->query($stmt);
     }
     return true;
 }
 public function getExcerpts()
 {
     if (count($this->matches) < 1) {
         return false;
     }
     $excerpt_options = array('query_mode' => $this->match_mode, 'before_match' => $this->excerpt_placeholder . '-before', 'after_match' => $this->excerpt_placeholder . '-after', 'allow_empty' => true);
     $excerpts = array();
     foreach ($this->matches as $issue_id => $matches) {
         $excerpt = array('issue' => array(), 'email' => array(), 'phone' => array(), 'note' => array());
         foreach ($matches as $match) {
             if ($match['index'] == 'issue') {
                 $issue = Issue::getDetails($issue_id);
                 $documents = array($issue['iss_summary']);
                 $res = $this->sphinx->BuildExcerpts($documents, 'issue_stemmed', $this->keywords, $excerpt_options);
                 if ($res[0] != $issue['iss_summary']) {
                     $excerpt['issue']['summary'] = self::cleanUpExcerpt($res[0]);
                 }
                 $documents = array($issue['iss_original_description']);
                 $res = $this->sphinx->BuildExcerpts($documents, 'issue_stemmed', $this->keywords, $excerpt_options);
                 if ($res[0] != $issue['iss_original_description']) {
                     $excerpt['issue']['description'] = self::cleanUpExcerpt($res[0]);
                     error_log(print_r($excerpt['issue']['description'], 1));
                 }
             } elseif ($match['index'] == 'email') {
                 $email = Support::getEmailDetails(null, $match['match_id']);
                 $documents = array($email['sup_subject'] . "\n" . $email['message']);
                 $res = $this->sphinx->BuildExcerpts($documents, 'email_stemmed', $this->keywords, $excerpt_options);
                 $excerpt['email'][Support::getSequenceByID($match['match_id'])] = self::cleanUpExcerpt($res[0]);
             } elseif ($match['index'] == 'phone') {
                 $phone_call = Phone_Support::getDetails($match['match_id']);
                 $documents = array($phone_call['phs_description']);
                 $res = $this->sphinx->BuildExcerpts($documents, 'phonesupport_stemmed', $this->keywords, $excerpt_options);
                 $excerpt['phone'][] = self::cleanUpExcerpt($res[0]);
             } elseif ($match['index'] == 'note') {
                 $note = Note::getDetails($match['match_id']);
                 $documents = array($note['not_title'] . "\n" . $note['not_note']);
                 $res = $this->sphinx->BuildExcerpts($documents, 'note_stemmed', $this->keywords, $excerpt_options);
                 $note_seq = Note::getNoteSequenceNumber($issue_id, $match['match_id']);
                 $excerpt['note'][$note_seq] = self::cleanUpExcerpt($res[0]);
             }
         }
         foreach ($excerpt as $key => $val) {
             if (count($val) < 1) {
                 unset($excerpt[$key]);
             }
         }
         $excerpts[$issue_id] = $excerpt;
     }
     return $excerpts;
 }
Пример #4
0
 * please see the COPYING and AUTHORS files
 * that were distributed with this source code.
 */
require_once __DIR__ . '/../../init.php';
$tpl = new Template_Helper();
$tpl->setTemplate('manage/phone_categories.tpl.html');
Auth::checkAuthentication();
$role_id = Auth::getCurrentRole();
if ($role_id < User::ROLE_MANAGER) {
    Misc::setMessage(ev_gettext('Sorry, you are not allowed to access this page.'), Misc::MSG_ERROR);
    $tpl->displayTemplate();
    exit;
}
@($prj_id = $_POST['prj_id'] ? $_POST['prj_id'] : $_GET['prj_id']);
$tpl->assign('project', Project::getDetails($prj_id));
if (@$_POST['cat'] == 'new') {
    $res = Phone_Support::insertCategory();
    $tpl->assign('result', $res);
    Misc::mapMessages($res, array(1 => array(ev_gettext('Thank you, the phone category was added successfully.'), Misc::MSG_INFO), -1 => array(ev_gettext('An error occurred while trying to add the phone category.'), Misc::MSG_ERROR), -2 => array(ev_gettext('Please enter the title for this new phone category.'), Misc::MSG_ERROR)));
} elseif (@$_POST['cat'] == 'update') {
    $res = Phone_Support::updateCategory();
    $tpl->assign('result', $res);
    Misc::mapMessages($res, array(1 => array(ev_gettext('Thank you, the phone category was updated successfully.'), Misc::MSG_INFO), -1 => array(ev_gettext('An error occurred while trying to uodate the phone category.'), Misc::MSG_ERROR), -2 => array(ev_gettext('Please enter the title for this phone category.'), Misc::MSG_ERROR)));
} elseif (@$_POST['cat'] == 'delete') {
    Phone_Support::removeCategory();
}
if (@$_GET['cat'] == 'edit') {
    $tpl->assign('info', Phone_Support::getCategoryDetails($_GET['id']));
}
$tpl->assign('list', Phone_Support::getCategoryList($prj_id));
$tpl->displayTemplate();
Пример #5
0
    $tpl->assign('remove_file_result', $res);
} elseif ($cat == 'remove_checkin') {
    $res = SCM::remove($items);
    $tpl->assign('remove_checkin_result', $res);
} elseif ($cat == 'unassign') {
    $res = Issue::deleteUserAssociation($iss_id, $usr_id);
    Workflow::handleAssignmentChange($prj_id, $iss_id, Auth::getUserID(), Issue::getDetails($iss_id), Issue::getAssignedUserIDs($iss_id));
    $tpl->assign('unassign_result', $res);
} elseif ($cat == 'remove_email') {
    $res = Support::removeEmails();
    $tpl->assign('remove_email_result', $res);
} elseif ($cat == 'clear_duplicate') {
    $res = Issue::clearDuplicateStatus($iss_id);
    $tpl->assign('clear_duplicate_result', $res);
} elseif ($cat == 'delete_phone') {
    $res = Phone_Support::remove($id);
    $tpl->assign('delete_phone_result', $res);
} elseif ($cat == 'new_status') {
    $res = Issue::setStatus($iss_id, $status_id, true);
    if ($res == 1) {
        History::add($iss_id, $usr_id, 'status_changed', "Issue manually set to status '{status}' by {user}", array('status' => Status::getStatusTitle($status_id), 'user' => User::getFullName($usr_id)));
    }
    $tpl->assign('new_status_result', $res);
} elseif ($cat == 'authorize_reply') {
    $res = Authorized_Replier::addUser($iss_id, $usr_id);
    $tpl->assign('authorize_reply_result', $res);
} elseif ($cat == 'remove_quarantine') {
    if (Auth::getCurrentRole() > User::getRoleID('Developer')) {
        $res = Issue::setQuarantine($iss_id, 0);
        $tpl->assign('remove_quarantine_result', $res);
    }
Пример #6
0
// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        |
// | GNU General Public License for more details.                         |
// |                                                                      |
// | You should have received a copy of the GNU General Public License    |
// | along with this program; if not, write to:                           |
// |                                                                      |
// | Free Software Foundation, Inc.                                       |
// | 51 Franklin Street, Suite 330                                          |
// | Boston, MA 02110-1301, USA.                                          |
// +----------------------------------------------------------------------+
// | Authors: João Prado Maia <*****@*****.**>                             |
// +----------------------------------------------------------------------+
require_once dirname(__FILE__) . '/../init.php';
$tpl = new Template_Helper();
$tpl->setTemplate('add_phone_entry.tpl.html');
Auth::checkAuthentication(APP_COOKIE, 'index.php?err=5', true);
$issue_id = @$_POST['issue_id'] ? $_POST['issue_id'] : $_GET['iss_id'];
if (!Issue::canAccess($issue_id, Auth::getUserID()) || Auth::getCurrentRole() <= User::getRoleID('Customer')) {
    $tpl = new Template_Helper();
    $tpl->setTemplate('permission_denied.tpl.html');
    $tpl->displayTemplate();
    exit;
}
if (@$_POST['cat'] == 'add_phone') {
    $res = Phone_Support::insert();
    $tpl->assign('add_phone_result', $res);
}
$prj_id = Issue::getProjectID($issue_id);
$usr_id = Auth::getUserID();
$tpl->assign(array('issue_id' => $issue_id, 'phone_categories' => Phone_Support::getCategoryAssocList($prj_id), 'current_user_prefs' => Prefs::get($usr_id)));
$tpl->displayTemplate();
Пример #7
0
/**
 * Selects a phone support entry from the table and returns the contents.
 *
 * @param   string $id The phone support entry ID.
 * @return  A string containing the description.
 */
function getPhoneSupport($id)
{
    $res = Phone_Support::getDetails($id);
    if (!Issue::canAccess($res['phs_iss_id'], $GLOBALS['usr_id'])) {
        return '';
    }
    if (empty($_GET['ec_id'])) {
        return $res['phs_description'];
    }
    return Link_Filter::processText(Auth::getCurrentProject(), nl2br(htmlspecialchars($res['phs_description'])));
}
Пример #8
0
    $tpl->assign("remove_file_result", $res);
} elseif (@$HTTP_POST_VARS["cat"] == "remove_checkin") {
    $res = SCM::remove();
    $tpl->assign("remove_checkin_result", $res);
} elseif (@$HTTP_GET_VARS['cat'] == 'unassign') {
    $res = Issue::deleteUserAssociation($HTTP_GET_VARS["iss_id"], $usr_id);
    Workflow::handleAssignmentChange($prj_id, $HTTP_GET_VARS["iss_id"], Auth::getUserID(), Issue::getDetails($HTTP_GET_VARS["iss_id"]), Issue::getAssignedUserIDs($HTTP_GET_VARS["iss_id"]));
    $tpl->assign('unassign_result', $res);
} elseif (@$HTTP_POST_VARS["cat"] == "remove_email") {
    $res = Support::removeEmails();
    $tpl->assign("remove_email_result", $res);
} elseif (@$HTTP_GET_VARS["cat"] == "clear_duplicate") {
    $res = Issue::clearDuplicateStatus($HTTP_GET_VARS["iss_id"]);
    $tpl->assign("clear_duplicate_result", $res);
} elseif (@$HTTP_GET_VARS["cat"] == "delete_phone") {
    $res = Phone_Support::remove($HTTP_GET_VARS["id"]);
    $tpl->assign("delete_phone_result", $res);
} elseif (@$HTTP_GET_VARS["cat"] == "new_status") {
    // XXX: need to call the workflow api in the following function?
    $res = Issue::setStatus($HTTP_GET_VARS["iss_id"], $HTTP_GET_VARS["new_sta_id"], true);
    if ($res == 1) {
        History::add($HTTP_GET_VARS["iss_id"], $usr_id, History::getTypeID('status_changed'), "Issue manually set to status '" . Status::getStatusTitle($HTTP_GET_VARS["new_sta_id"]) . "' by " . User::getFullName($usr_id));
    }
    $tpl->assign("new_status_result", $res);
} elseif (@$HTTP_GET_VARS["cat"] == "new_category") {
    $res = Issue::setCategory($HTTP_GET_VARS["iss_id"], $HTTP_GET_VARS["iss_prc_id"], true);
    if ($res == 1) {
        History::add($HTTP_GET_VARS["iss_id"], $usr_id, History::getTypeID('status_changed'), "Issue manually set to category '" . Category::getTitle($HTTP_GET_VARS["iss_prc_id"]) . "' by " . User::getFullName($usr_id));
    }
    $tpl->assign("new_status_result", $res);
} elseif (@$HTTP_GET_VARS["cat"] == "new_project") {
Пример #9
0
 /**
  * Returns the data used by the weekly report.
  *
  * @access  public
  * @param   string $usr_id The ID of the user this report is for.
  * @param   string The start date of this report.
  * @param   string The end date of this report.
  * @param   boolean If closed issues should be separated from other issues.
  * @return  array An array of data containing all the elements of the weekly report.
  */
 function getWeeklyReport($usr_id, $start, $end, $separate_closed = false)
 {
     $usr_id = Misc::escapeInteger($usr_id);
     // figure out timezone
     $user_prefs = Prefs::get($usr_id);
     $tz = @$user_prefs["timezone"];
     $start_dt = new Date();
     $end_dt = new Date();
     // set timezone to that of user.
     $start_dt->setTZById($tz);
     $end_dt->setTZById($tz);
     // set the dates in the users time zone
     $start_dt->setDate($start . " 00:00:00");
     $end_dt->setDate($end . " 23:59:59");
     // convert time to GMT
     $start_dt->toUTC();
     $end_dt->toUTC();
     $start_ts = $start_dt->getDate();
     $end_ts = $end_dt->getDate();
     $time_tracking = Time_Tracking::getSummaryByUser($usr_id, $start_ts, $end_ts);
     // replace spaces in index with _ and calculate total time
     $total_time = 0;
     foreach ($time_tracking as $category => $data) {
         unset($time_tracking[$category]);
         $time_tracking[str_replace(" ", "_", $category)] = $data;
         $total_time += $data["total_time"];
     }
     // get count of issues assigned in week of report.
     $stmt = "SELECT\n                    COUNT(*)\n                 FROM\n                    " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "issue,\n                    " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "issue_user,\n                    " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "status\n                 WHERE\n                    iss_id = isu_iss_id AND\n                    iss_sta_id = sta_id AND\n                    isu_usr_id = {$usr_id} AND\n                    isu_assigned_date BETWEEN '{$start_ts}' AND '{$end_ts}'";
     $newly_assigned = $GLOBALS["db_api"]->dbh->getOne($stmt);
     if (PEAR::isError($newly_assigned)) {
         Error_Handler::logError(array($newly_assigned->getMessage(), $newly_assigned->getDebugInfo()), __FILE__, __LINE__);
     }
     $email_count = array("associated" => Support::getSentEmailCountByUser($usr_id, $start_ts, $end_ts, true), "other" => Support::getSentEmailCountByUser($usr_id, $start_ts, $end_ts, false));
     $data = array("start" => str_replace('-', '.', $start), "end" => str_replace('-', '.', $end), "user" => User::getDetails($usr_id), "group_name" => Group::getName(User::getGroupID($usr_id)), "issues" => History::getTouchedIssuesByUser($usr_id, $start_ts, $end_ts, $separate_closed), "status_counts" => History::getTouchedIssueCountByStatus($usr_id, $start_ts, $end_ts), "new_assigned_count" => $newly_assigned, "time_tracking" => $time_tracking, "email_count" => $email_count, "phone_count" => Phone_Support::getCountByUser($usr_id, $start_ts, $end_ts), "note_count" => Note::getCountByUser($usr_id, $start_ts, $end_ts), "total_time" => Misc::getFormattedTime($total_time, false));
     return $data;
 }
Пример #10
0
                $show_category = 0;
            }
            $cookie = Auth::getCookieInfo(APP_PROJECT_COOKIE);
            if (!empty($auto_switched_from)) {
                $tpl->assign(array("project_auto_switched" => 1, "old_project" => Project::getName($auto_switched_from)));
            }
            $setup = Setup::load();
            $tpl->assign("allow_unassigned_issues", @$setup["allow_unassigned_issues"]);
            $tpl->assign(array('next_issue' => @$sides['next'], 'previous_issue' => @$sides['previous'], 'subscribers' => Notification::getSubscribers($issue_id), 'custom_fields' => Custom_Field::getListByIssue($prj_id, $issue_id), 'files' => Attachment::getList($issue_id), 'emails' => Support::getEmailsByIssue($issue_id), 'zones' => Date_API::getTimezoneList(), 'users' => Project::getUserAssocList($prj_id, 'active', User::getRoleID('Customer')), 'ema_id' => Email_Account::getEmailAccount(), 'max_attachment_size' => Attachment::getMaxAttachmentSize(), 'show_releases' => $show_releases, 'show_category' => $show_category, 'categories' => Category::getAssocList($prj_id), 'quarantine' => Issue::getQuarantineInfo($issue_id)));
            if ($role_id != User::getRoleID('customer')) {
                if (@$_REQUEST['show_all_drafts'] == 1) {
                    $show_all_drafts = true;
                } else {
                    $show_all_drafts = false;
                }
                if (Workflow::hasWorkflowIntegration($prj_id)) {
                    $statuses = Workflow::getAllowedStatuses($prj_id, $issue_id);
                    // if currently selected release is not on list, go ahead and add it.
                } else {
                    $statuses = Status::getAssocStatusList($prj_id);
                }
                if (!empty($details['iss_sta_id']) && empty($statuses[$details['iss_sta_id']])) {
                    $statuses[$details['iss_sta_id']] = Status::getStatusTitle($details['iss_sta_id']);
                }
                $time_entries = Time_Tracking::getListing($issue_id);
                $tpl->assign(array('notes' => Note::getListing($issue_id), 'is_user_assigned' => Issue::isAssignedToUser($issue_id, $usr_id), 'is_user_authorized' => Authorized_Replier::isUserAuthorizedReplier($issue_id, $usr_id), 'phone_entries' => Phone_Support::getListing($issue_id), 'phone_categories' => Phone_Support::getCategoryAssocList($prj_id), 'checkins' => SCM::getCheckinList($issue_id), 'time_categories' => Time_Tracking::getAssocCategories(), 'time_entries' => $time_entries['list'], 'total_time_spent' => $time_entries['total_time_spent'], 'impacts' => Impact_Analysis::getListing($issue_id), 'statuses' => $statuses, 'drafts' => Draft::getList($issue_id, $show_all_drafts), 'groups' => Group::getAssocList($prj_id)));
            }
        }
    }
}
$tpl->displayTemplate();
Пример #11
0
/**
 * Selects a phone support entry from the table and returns the contents.
 * 
 * @param   string $id The phone support entry ID.
 * @return  A string containing the description.
 */
function getPhoneSupport($id)
{
    $res = Phone_Support::getDetails($id);
    if (!empty($_GET["ec_id"])) {
        return Link_Filter::processText(Auth::getCurrentProject(), nl2br(htmlspecialchars($_GET["ec_id"] . ":" . $id . ":" . $res["phs_description"])));
    } else {
        return $res["phs_description"];
    }
}
Пример #12
0
 /**
  * Method used to remove all issues associated with a specific list of
  * projects.
  *
  * @access  public
  * @param   array $ids The list of projects to look for
  * @return  boolean
  */
 function removeByProjects($ids)
 {
     $items = @implode(", ", Misc::escapeInteger($ids));
     $stmt = "SELECT\n                    iss_id\n                 FROM\n                    " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "issue\n                 WHERE\n                    iss_prj_id IN ({$items})";
     $res = $GLOBALS["db_api"]->dbh->getCol($stmt);
     if (PEAR::isError($res)) {
         Error_Handler::logError(array($res->getMessage(), $res->getDebugInfo()), __FILE__, __LINE__);
         return false;
     } else {
         if (count($res) > 0) {
             Issue::deleteAssociations($res);
             Attachment::removeByIssues($res);
             SCM::removeByIssues($res);
             Impact_Analysis::removeByIssues($res);
             Issue::deleteUserAssociations($res);
             Note::removeByIssues($res);
             Time_Tracking::removeByIssues($res);
             Notification::removeByIssues($res);
             Custom_Field::removeByIssues($res);
             Phone_Support::removeByIssues($res);
             History::removeByIssues($res);
             // now really delete the issues
             $items = implode(", ", $res);
             $stmt = "DELETE FROM\n                            " . APP_DEFAULT_DB . "." . APP_TABLE_PREFIX . "issue\n                         WHERE\n                            iss_id IN ({$items})";
             $GLOBALS["db_api"]->dbh->query($stmt);
         }
         return true;
     }
 }