function scm_ping($module, $username, $scm_name, $issues, $commit_msg) { // module is per file (svn hook) if (is_array($module)) { $module = null; } // process checkins for each issue foreach ($issues as $issue_id) { // check early if issue exists to report proper message back // workflow needs to know project_id to find out which workflow class to use. $prj_id = Issue::getProjectID($issue_id); if (empty($prj_id)) { echo "issue #{$issue_id} not found\n"; continue; } $files = array(); $nfiles = count($_GET['files']); for ($y = 0; $y < $nfiles; $y++) { $file = array('file' => $_GET['files'][$y], 'old_version' => isset($_GET['old_versions'][$y]) ? $_GET['old_versions'][$y] : null, 'new_version' => isset($_GET['new_versions'][$y]) ? $_GET['new_versions'][$y] : null, 'module' => isset($module) ? $module : $_GET['module'][$y]); $files[] = $file; } $commit_time = Date_Helper::getCurrentDateGMT(); SCM::addCheckins($issue_id, $commit_time, $scm_name, $username, $commit_msg, $files); // print report to stdout of commits so hook could report status back to commiter $details = Issue::getDetails($issue_id); echo "#{$issue_id} - {$details['iss_summary']} ({$details['sta_title']})\n"; } }
/** * Method used to save the login information into a log file. It will be * useful for administrative purposes, so we know which customers were able * to login. * * @param string $email The email associated with the user * @param string $type Whether it was a successful login or not * @param string $extra The reason for not being a successful login */ public static function saveLoginAttempt($email, $type, $extra = false) { $msg = Date_Helper::getCurrentDateGMT() . " - Login attempt by '{$email}' was "; if ($type == 'success') { $msg .= "successful.\n"; } else { $msg .= "not successful because of '{$extra}'.\n"; } file_put_contents(APP_LOGIN_LOG, $msg, FILE_APPEND); }
/** * Method used to log the changes made against a specific issue. * * @param integer $iss_id The issue ID * @param integer $usr_id The ID of the user. * @param integer|string $htt_id The type ID of this history event. * @param string $summary The summary of the changes * @param array $context parameters used in summary */ public static function add($iss_id, $usr_id, $htt_id, $summary, $context = array()) { if (!is_numeric($htt_id)) { $htt_id = History::getTypeID($htt_id); } $params = array('his_iss_id' => $iss_id, 'his_usr_id' => $usr_id, 'his_created_date' => Date_Helper::getCurrentDateGMT(), 'his_summary' => $summary, 'his_context' => json_encode($context), 'his_htt_id' => $htt_id); $stmt = 'INSERT INTO {{%issue_history}} SET ' . DB_Helper::buildSet($params); try { DB_Helper::getInstance()->query($stmt, $params); } catch (DbException $e) { } }
public static function saveToken($usr_id, $token) { $sql = 'INSERT INTO {{%api_token}} SET apt_usr_id = ?, apt_created = ?, apt_token = ?'; try { $res = DB_Helper::getInstance()->query($sql, array($usr_id, Date_Helper::getCurrentDateGMT(), $token)); } catch (DbException $e) { return -1; } }
/** * Method used to update the details of a specific reminder condition. * * @return integer 1 if the update worked, -1 or -2 otherwise */ public static function update() { $stmt = 'UPDATE {{%reminder_level_condition}} SET rlc_last_updated_date=?, rlc_rmf_id=?, rlc_rmo_id=?, rlc_value=?, rlc_comparison_rmf_id = ? WHERE rlc_id=?'; $params = array(Date_Helper::getCurrentDateGMT(), $_POST['field'], $_POST['operator'], @$_POST['value'], @$_POST['comparison_field'], $_POST['id']); try { DB_Helper::getInstance()->query($stmt, $params); } catch (DbException $e) { return -1; } return 1; }
public static function addPartnerToIssue($iss_id, $par_code) { $current_partners = self::getPartnerCodesByIssue($iss_id); if (!in_array($par_code, $current_partners)) { $params = array($iss_id, $par_code, Date_Helper::getCurrentDateGMT()); $sql = 'INSERT INTO {{%issue_partner}} SET ipa_iss_id = ?, ipa_par_code = ?, ipa_created_date = ?'; try { DB_Helper::getInstance()->query($sql, $params); } catch (DbException $e) { return false; } $backend = self::getBackend($par_code); $backend->issueAdded($iss_id); $usr_id = Auth::getUserID(); History::add($iss_id, $usr_id, 'partner_added', "Partner '{partner}' added to issue by {user}", array('partner' => $backend->getName(), 'user' => User::getFullName($usr_id))); } return true; }
/** * Method used to add a new subscriber manually, by using the * email notification interface. * * @param integer $usr_id The user ID of the person performing this change * @param integer $issue_id The issue ID * @param string $email The email address to subscribe * @param array $actions The actions to subcribe to * @return integer 1 if the update worked, -1 otherwise */ public static function subscribeEmail($usr_id, $issue_id, $email, $actions) { $email = Mail_Helper::getEmailAddress($email); if (!is_string($email)) { return -1; } $email = strtolower($email); // first check if this is an actual user or just an email address $sub_usr_id = User::getUserIDByEmail($email, true); if (!empty($sub_usr_id)) { return self::subscribeUser($usr_id, $issue_id, $sub_usr_id, $actions); } $prj_id = Issue::getProjectID($issue_id); // call workflow to modify actions or cancel adding this user. $subscriber_usr_id = false; $workflow = Workflow::handleSubscription($prj_id, $issue_id, $subscriber_usr_id, $email, $actions); if ($workflow === false) { // cancel subscribing the user return -2; } // manual check to prevent duplicates if (!empty($email)) { $stmt = 'SELECT COUNT(sub_id) FROM {{%subscription}} WHERE sub_iss_id=? AND sub_email=?'; $total = DB_Helper::getInstance()->getOne($stmt, array($issue_id, $email)); if ($total > 0) { return -1; } } $stmt = "INSERT INTO\n {{%subscription}}\n (\n sub_iss_id,\n sub_usr_id,\n sub_created_date,\n sub_level,\n sub_email\n ) VALUES (\n ?,\n 0,\n ?,\n 'issue',\n ?\n )"; try { DB_Helper::getInstance()->query($stmt, array($issue_id, Date_Helper::getCurrentDateGMT(), $email)); } catch (DbException $e) { return -1; } $sub_id = DB_Helper::get_last_insert_id(); foreach ($actions as $sbt_type) { self::addType($sub_id, $sbt_type); } // need to mark the issue as updated Issue::markAsUpdated($issue_id); // need to save a history entry for this // FIXME: XSS possible as $email is not escaped for html? History::add($issue_id, $usr_id, 'notification_added', "Notification list entry ('{subscriber}') added by {user}", array('subscriber' => $email, 'user' => User::getFullName($usr_id))); return 1; }
/** * Adds a quick note for the specified customer. * * @param integer $prj_id The project ID * @param integer $customer_id The id of the customer. * @param string $note The note to add. * @return int */ public static function insertNote($prj_id, $customer_id, $note) { $stmt = 'INSERT INTO {{%customer_note}} ( cno_prj_id, cno_customer_id, cno_created_date, cno_updated_date, cno_note ) VALUES ( ?, ?, ?, ?, ? )'; try { DB_Helper::getInstance()->query($stmt, array($prj_id, $customer_id, Date_Helper::getCurrentDateGMT(), Date_Helper::getCurrentDateGMT(), $note)); } catch (DbException $e) { return -1; } return 1; }
/** * Method used to add a new project to the system. * * @return integer 1 if the update worked, -1 or -2 otherwise */ public static function insert() { if (Validation::isWhitespace($_POST['title'])) { return -2; } $stmt = 'INSERT INTO {{%project}} ( prj_created_date, prj_title, prj_status, prj_lead_usr_id, prj_initial_sta_id, prj_outgoing_sender_name, prj_outgoing_sender_email, prj_mail_aliases, prj_remote_invocation, prj_customer_backend, prj_workflow_backend ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )'; try { DB_Helper::getInstance()->query($stmt, array(Date_Helper::getCurrentDateGMT(), $_POST['title'], $_POST['status'], $_POST['lead_usr_id'], $_POST['initial_status'], $_POST['outgoing_sender_name'], $_POST['outgoing_sender_email'], $_POST['mail_aliases'], $_POST['remote_invocation'], $_POST['customer_backend'], $_POST['workflow_backend'])); } catch (DbException $e) { return -1; } $new_prj_id = DB_Helper::get_last_insert_id(); foreach ($_POST['users'] as $user) { if ($user == $_POST['lead_usr_id']) { $role_id = User::getRoleID('Manager'); } else { $role_id = User::getRoleID('Standard User'); } self::associateUser($new_prj_id, $user, $role_id); } foreach ($_POST['statuses'] as $sta_id) { Status::addProjectAssociation($sta_id, $new_prj_id); } Display_Column::setupNewProject($new_prj_id); // insert default timetracking categories Time_Tracking::addProjectDefaults($new_prj_id); return 1; }
/** * Routes an email to the correct issue. * * @param string $full_message The full email message, including headers * @return mixed true or array(ERROR_CODE, ERROR_STRING) in case of failure */ public static function route_emails($full_message) { // need some validation here if (empty($full_message)) { return array(self::EX_NOINPUT, ev_gettext('Error: The email message was empty') . ".\n"); } // save the full message for logging purposes Support::saveRoutedEmail($full_message); // check if the email routing interface is even supposed to be enabled $setup = Setup::get(); if ($setup['email_routing']['status'] != 'enabled') { return array(self::EX_CONFIG, ev_gettext('Error: The email routing interface is disabled.') . "\n"); } if (empty($setup['email_routing']['address_prefix'])) { return array(self::EX_CONFIG, ev_gettext('Error: Please configure the email address prefix.') . "\n"); } if (empty($setup['email_routing']['address_host'])) { return array(self::EX_CONFIG, ev_gettext('Error: Please configure the email address domain.') . "\n"); } // associate routed emails to the internal system account $sys_account = User::getNameEmail(APP_SYSTEM_USER_ID); if (empty($sys_account['usr_email'])) { return array(self::EX_CONFIG, ev_gettext('Error: The associated user for the email routing interface needs to be set.') . "\n"); } unset($sys_account); // join the Content-Type line (for easier parsing?) if (preg_match('/^boundary=/m', $full_message)) { $pattern = "#(Content-Type: multipart/.+); ?\r?\n(boundary=.*)\$#im"; $replacement = '$1; $2'; $full_message = preg_replace($pattern, $replacement, $full_message); } // remove the reply-to: header if (preg_match('/^reply-to:.*/im', $full_message)) { $full_message = preg_replace("/^(reply-to:).*\n/im", '', $full_message, 1); } AuthCookie::setAuthCookie(APP_SYSTEM_USER_ID); $structure = Mime_Helper::decode($full_message, true, true); // find which issue ID this email refers to if (isset($structure->headers['to'])) { $issue_id = self::getMatchingIssueIDs($structure->headers['to'], 'email'); } // we need to try the Cc header as well if (empty($issue_id) and isset($structure->headers['cc'])) { $issue_id = self::getMatchingIssueIDs($structure->headers['cc'], 'email'); } if (empty($issue_id)) { return array(self::EX_DATAERR, ev_gettext('Error: The routed email had no associated Eventum issue ID or had an invalid recipient address.') . "\n"); } $issue_prj_id = Issue::getProjectID($issue_id); if (empty($issue_prj_id)) { return array(self::EX_DATAERR, ev_gettext('Error: The routed email had no associated Eventum issue ID or had an invalid recipient address.') . "\n"); } $email_account_id = Email_Account::getEmailAccount($issue_prj_id); if (empty($email_account_id)) { return array(self::EX_CONFIG, ev_gettext('Error: Please provide the email account ID.') . "\n"); } $body = $structure->body; // hack for clients that set more then one from header if (is_array($structure->headers['from'])) { $structure->headers['from'] = $structure->headers['from'][0]; } // associate the email to the issue $parts = array(); Mime_Helper::parse_output($structure, $parts); // get the sender's email address $sender_email = strtolower(Mail_Helper::getEmailAddress($structure->headers['from'])); // strip out the warning message sent to staff users if ($setup['email_routing']['status'] == 'enabled' && $setup['email_routing']['warning']['status'] == 'enabled') { $full_message = Mail_Helper::stripWarningMessage($full_message); $body = Mail_Helper::stripWarningMessage($body); } $prj_id = Issue::getProjectID($issue_id); AuthCookie::setAuthCookie(APP_SYSTEM_USER_ID); AuthCookie::setProjectCookie($prj_id); if (Mime_Helper::hasAttachments($structure)) { $has_attachments = 1; } else { $has_attachments = 0; } // remove certain CC addresses if (!empty($structure->headers['cc']) && $setup['smtp']['save_outgoing_email'] == 'yes') { $ccs = explode(',', @$structure->headers['cc']); foreach ($ccs as $i => $address) { if (Mail_Helper::getEmailAddress($address) == $setup['smtp']['save_address']) { unset($ccs[$i]); } } $structure->headers['cc'] = implode(', ', $ccs); } // Remove excess Re's $structure->headers['subject'] = Mail_Helper::removeExcessRe(@$structure->headers['subject'], true); $t = array('issue_id' => $issue_id, 'ema_id' => $email_account_id, 'message_id' => @$structure->headers['message-id'], 'date' => Date_Helper::getCurrentDateGMT(), 'from' => @$structure->headers['from'], 'to' => @$structure->headers['to'], 'cc' => @$structure->headers['cc'], 'subject' => @$structure->headers['subject'], 'body' => @$body, 'full_email' => @$full_message, 'has_attachment' => $has_attachments, 'headers' => @$structure->headers); // automatically associate this incoming email with a customer if (CRM::hasCustomerIntegration($prj_id)) { $crm = CRM::getInstance($prj_id); if (!empty($structure->headers['from'])) { try { $contact = $crm->getContactByEmail($sender_email); $issue_contract = $crm->getContract(Issue::getContractID($issue_id)); if ($contact->canAccessContract($issue_contract)) { $t['customer_id'] = $issue_contract->getCustomerID(); } } catch (CRMException $e) { } } } if (empty($t['customer_id'])) { $t['customer_id'] = null; } if (Support::blockEmailIfNeeded($t)) { return true; } // re-write Threading headers if needed list($t['full_email'], $t['headers']) = Mail_Helper::rewriteThreadingHeaders($t['issue_id'], $t['full_email'], $t['headers'], 'email'); $res = Support::insertEmail($t, $structure, $sup_id); if ($res != -1) { Support::extractAttachments($issue_id, $structure); // notifications about new emails are always external $internal_only = false; $assignee_only = false; // special case when emails are bounced back, so we don't want a notification to customers about those if (Notification::isBounceMessage($sender_email)) { // broadcast this email only to the assignees for this issue $internal_only = true; $assignee_only = true; } Notification::notifyNewEmail(Auth::getUserID(), $issue_id, $t, $internal_only, $assignee_only, '', $sup_id); // try to get usr_id of sender, if not, use system account $usr_id = User::getUserIDByEmail(Mail_Helper::getEmailAddress($structure->headers['from'])); if (!$usr_id) { $usr_id = APP_SYSTEM_USER_ID; } // mark this issue as updated if (!empty($t['customer_id']) && $t['customer_id'] != null) { Issue::markAsUpdated($issue_id, 'customer action'); } else { if (!empty($usr_id) && $usr_id != APP_SYSTEM_USER_ID && User::getRoleByUser($usr_id, $prj_id) > User::ROLE_CUSTOMER) { Issue::markAsUpdated($issue_id, 'staff response'); } else { Issue::markAsUpdated($issue_id, 'user response'); } } // log routed email History::add($issue_id, $usr_id, 'email_routed', 'Email routed from {from}', array('from' => $structure->headers['from'])); } return true; }
/** * Method used to generate an SQL query to be used in debugging the reminder * conditions. * * @param integer $rem_id The reminder ID * @param integer $rma_id The reminder action ID * @return string The SQL query */ public static function getSQLQuery($rem_id, $rma_id) { $reminder = self::getDetails($rem_id); $conditions = Reminder_Condition::getList($rma_id); $stmt = 'SELECT iss_id FROM {{%issue}}'; $products = self::getAssociatedProducts($reminder['rem_id']); if (count($products) > 0) { $stmt .= ', issue_product_version'; } $stmt .= self::getWhereClause($reminder, $conditions); // can't rely on the mysql server's timezone setting, so let's use gmt dates throughout $stmt = str_replace('UNIX_TIMESTAMP()', "UNIX_TIMESTAMP('" . Date_Helper::getCurrentDateGMT() . "')", $stmt); return $stmt; }
/** * Method used to add a FAQ entry to the system. * * @return integer 1 if the insert worked, -1 otherwise */ public static function insert() { if (Validation::isWhitespace($_POST['title'])) { return -2; } if (Validation::isWhitespace($_POST['message'])) { return -3; } $stmt = 'INSERT INTO {{%faq}} ( faq_prj_id, faq_usr_id, faq_created_date, faq_title, faq_message, faq_rank ) VALUES ( ?, ?, ?, ?, ?, ? )'; $params = array($_POST['project'], Auth::getUserID(), Date_Helper::getCurrentDateGMT(), $_POST['title'], $_POST['message'], $_POST['rank']); try { DB_Helper::getInstance()->query($stmt, $params); } catch (DbException $e) { return -1; } $new_faq_id = DB_Helper::get_last_insert_id(); if (isset($_POST['support_levels']) && count($_POST['support_levels']) > 0) { // now populate the faq-support level mapping table foreach ($_POST['support_levels'] as $support_level_id) { self::addSupportLevelAssociation($new_faq_id, $support_level_id); } } return 1; }
/** * Method used to add a new user to the system. * * @param array $user The array of user information * @return integer 1 if the update worked, -1 otherwise */ public static function insert($user) { $projects = array(); foreach ($user['role'] as $prj_id => $role) { if ($role < 1) { continue; } $projects[] = $prj_id; } $params = array(isset($user['customer_id']) ? $user['customer_id'] : null, isset($user['contact_id']) ? $user['contact_id'] : null, Date_Helper::getCurrentDateGMT(), Auth::hashPassword($user['password']), $user['full_name'], $user['email'], !empty($user['grp_id']) ? $user['grp_id'] : null, $user['external_id'], isset($user['par_code']) ? $user['par_code'] : null); $stmt = 'INSERT INTO {{%user}} ( usr_customer_id, usr_customer_contact_id, usr_created_date, usr_password, usr_full_name, usr_email, usr_grp_id, usr_external_id, usr_par_code ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ? )'; try { DB_Helper::getInstance()->query($stmt, $params); } catch (DbException $e) { return -1; } $new_usr_id = DB_Helper::get_last_insert_id(); // add the project associations! $projects = array(); foreach ($user['role'] as $prj_id => $role) { if ($role < 1) { continue; } Project::associateUser($prj_id, $new_usr_id, $role); $projects[] = $prj_id; } Prefs::set($new_usr_id, Prefs::getDefaults($projects)); // send email to user Notification::notifyNewUser($new_usr_id, $user['password']); return $new_usr_id; }
<?php /** * Decode note bodies again which have failed to decode unicode html entities */ // notes that need to be decoded $res = $db->getAll('select not_id, not_iss_id, not_is_blocked, not_created_date, not_note, not_full_message from {{%note}} where not_note like ?', array('%�%')); $render_diff = function ($old, $new) { $diff = new Text_Diff(explode(PHP_EOL, $old), explode(PHP_EOL, $new)); $renderer = new Text_Diff_Renderer_unified(); return $renderer->render($diff); }; $now = Date_Helper::getCurrentDateGMT(); foreach ($res as $i => $row) { $email = Mime_Helper::decode($row['not_full_message'], true); $note = trim($email->body); if ($row['not_is_blocked']) { $note = Mail_Helper::getCannedBlockedMsgExplanation() . $note; } $diff = $render_diff($row['not_note'], $note); echo "--- issue #{$row['not_iss_id']} {$row['not_created_date']} GMT\n"; echo "+++ issue #{$row['not_iss_id']} {$now} GMT\n"; echo $diff; $db->query('UPDATE {{%note}} ' . 'SET not_note=? ' . 'WHERE not_id=?', array($note, $row['not_id'])); } echo count($res), " notes updated\n";
$prj_id = 1; // FIXME: Customer::getAssocList does not exist $customers = Customer::getAssocList($prj_id); foreach ($customers as $customer_id => $customer_name) { echo "Customer: {$customer_name}<br />\n"; $details = Customer::getDetails($prj_id, $customer_id); foreach ($details['contacts'] as $contact) { echo 'Contact: ' . $contact['first_name'] . ' ' . $contact['last_name'] . ' (' . $contact['email'] . ")<br />\n"; $contact_id = User::getUserIDByContactID($contact['contact_id']); if (empty($contact_id)) { $sql = 'INSERT INTO {{%user}} SET usr_created_date = ?, usr_full_name = ?, usr_email = ?, usr_customer_id = ?, usr_customer_contact_id = ?, usr_preferences = ?'; $params = array(Date_Helper::getCurrentDateGMT(), $contact['first_name'] . ' ' . $contact['last_name'], $contact['email'], $customer_id, $contact['contact_id'], Prefs::getDefaults(array($prj_id))); try { DB_Helper::getInstance()->query($sql, $params); } catch (DbException $e) { echo 'Error inserting user<br />'; } $new_usr_id = DB_Helper::get_last_insert_id(); Project::associateUser($prj_id, $new_usr_id, User::ROLE_CUSTOMER); } } echo '<hr />'; }
/** * Returns the SQL used to calculate the difference of 2 dates, not counting weekends. * This thing is truly a work of art, the type of art that throws lemon juice in your eye and then laughs. * If $end_date_field is null, the current date is used instead. * * @param string $start_date_field The name of the field the first date is. * @param string $end_date_field The name of the field where the second date is. * @return string The SQL used to compare the 2 dates. */ public static function getNoWeekendDateDiffSQL($start_date_field, $end_date_field = false) { if ($end_date_field == false) { $end_date_field = "'" . Date_Helper::getCurrentDateGMT() . "'"; } // this is crazy, but it does work. Anyone with a better solution email balsdorf@gmail.com $sql = "((UNIX_TIMESTAMP({$end_date_field}) - UNIX_TIMESTAMP({$start_date_field})) - (CASE\n WHEN DAYOFWEEK({$start_date_field}) = 1 THEN (floor(((TO_DAYS({$end_date_field}) - TO_DAYS({$start_date_field}))-1)/7) * 86400 * 2)\n WHEN DAYOFWEEK({$start_date_field}) = 2 THEN (floor(((TO_DAYS({$end_date_field}) - TO_DAYS({$start_date_field})))/7) * 86400 *2)\n WHEN DAYOFWEEK({$start_date_field}) = 3 THEN (floor(((TO_DAYS({$end_date_field}) - TO_DAYS({$start_date_field}))+1)/7) * 86400 *2)\n WHEN DAYOFWEEK({$start_date_field}) = 4 THEN (floor(((TO_DAYS({$end_date_field}) - TO_DAYS({$start_date_field}))+2)/7) * 86400 *2)\n WHEN DAYOFWEEK({$start_date_field}) = 5 THEN (floor(((TO_DAYS({$end_date_field}) - TO_DAYS({$start_date_field}))+3)/7) * 86400 *2)\n WHEN DAYOFWEEK({$start_date_field}) = 6 THEN (floor(((TO_DAYS({$end_date_field}) - TO_DAYS({$start_date_field}))+4)/7) * 86400 *2)\n WHEN DAYOFWEEK({$start_date_field}) = 7 THEN (floor(((TO_DAYS({$end_date_field}) - TO_DAYS({$start_date_field}))-2)/7) * 86400 *2)\n END) - (CASE\n WHEN DAYOFWEEK({$start_date_field}) = 7 THEN (86400 + (86400 - time_to_sec({$start_date_field})))\n WHEN DAYOFWEEK({$start_date_field}) = 1 THEN (86400 - time_to_sec({$start_date_field}))\n ELSE 0\n END) - CASE\n WHEN DAYOFWEEK({$end_date_field}) = 7 THEN time_to_sec({$end_date_field})\n WHEN DAYOFWEEK({$end_date_field}) = 1 THEN (86400 + time_to_sec({$end_date_field}))\n ELSE 0\n END)"; return str_replace("\n", ' ', $sql); }
/** * Method used to update an existing requirement with the appropriate * impact analysis. * * @param integer $isr_id The requirement ID * @return integer -1 if an error occurred or 1 otherwise */ public static function update($isr_id) { $stmt = 'SELECT isr_iss_id FROM {{%issue_requirement}} WHERE isr_id=?'; $issue_id = DB_Helper::getInstance()->getOne($stmt, array($isr_id)); // we are storing minutes, not hours $dev_time = $_POST['dev_time'] * 60; $usr_id = Auth::getUserID(); $stmt = 'UPDATE {{%issue_requirement}} SET isr_updated_usr_id=?, isr_updated_date=?, isr_dev_time=?, isr_impact_analysis=? WHERE isr_id=?'; $params = array($usr_id, Date_Helper::getCurrentDateGMT(), $dev_time, $_POST['impact_analysis'], $isr_id); try { DB_Helper::getInstance()->query($stmt, $params); } catch (DbException $e) { return -1; } Issue::markAsUpdated($issue_id); // need to save a history entry for this History::add($issue_id, $usr_id, 'impact_analysis_updated', 'Impact analysis submitted by {user}', array('user' => User::getFullName($usr_id))); return 1; }
/** * Method used to get the list of issues to be displayed in the grid layout. * * @param array $options The search parameters * @return string The where clause */ public static function buildWhereClause($options) { $usr_id = Auth::getUserID(); $prj_id = Auth::getCurrentProject(); $role_id = User::getRoleByUser($usr_id, $prj_id); $usr_details = User::getDetails($usr_id); $stmt = ' AND iss_usr_id = usr_id'; if ($role_id == User::getRoleID('Customer')) { $crm = CRM::getInstance($prj_id); $contact = $crm->getContact($usr_details['usr_customer_contact_id']); $stmt .= " AND iss_customer_contract_id IN('" . implode("','", $contact->getContractIDS()) . "')"; $stmt .= " AND iss_customer_id ='" . Auth::getCurrentCustomerID() . "'"; } elseif ($role_id == User::getRoleID('Reporter') && Project::getSegregateReporters($prj_id)) { $stmt .= " AND (\n iss_usr_id = {$usr_id} OR\n iur_usr_id = {$usr_id}\n )"; } if (!empty($usr_details['usr_par_code'])) { // restrict partners $stmt .= " AND ipa_par_code = '" . Misc::escapeString($usr_details['usr_par_code']) . "'"; } if (!empty($options['users'])) { $stmt .= " AND (\n"; if (stristr($options['users'], 'grp') !== false) { $chunks = explode(':', $options['users']); $stmt .= 'iss_grp_id = ' . Misc::escapeInteger($chunks[1]); } else { if ($options['users'] == '-1') { $stmt .= 'isu_usr_id IS NULL'; } elseif ($options['users'] == '-2') { $stmt .= 'isu_usr_id IS NULL OR isu_usr_id=' . $usr_id; } elseif ($options['users'] == '-3') { $stmt .= 'isu_usr_id = ' . $usr_id . ' OR iss_grp_id = ' . User::getGroupID($usr_id); } elseif ($options['users'] == '-4') { $stmt .= 'isu_usr_id IS NULL OR isu_usr_id = ' . $usr_id . ' OR iss_grp_id = ' . User::getGroupID($usr_id); } else { $stmt .= 'isu_usr_id =' . Misc::escapeInteger($options['users']); } } $stmt .= ')'; } if (!empty($options['reporter'])) { $stmt .= ' AND iss_usr_id = ' . Misc::escapeInteger($options['reporter']); } if (!empty($options['show_authorized_issues'])) { $stmt .= " AND (iur_usr_id={$usr_id})"; } if (!empty($options['show_notification_list_issues'])) { $stmt .= " AND (sub_usr_id={$usr_id})"; } if (!empty($options['keywords'])) { $stmt .= " AND (\n"; if ($options['search_type'] == 'all_text' && APP_ENABLE_FULLTEXT) { $stmt .= 'iss_id IN(' . implode(', ', self::getFullTextIssues($options)) . ')'; } elseif ($options['search_type'] == 'customer' && CRM::hasCustomerIntegration($prj_id)) { // check if the user is trying to search by customer name / email $crm = CRM::getInstance($prj_id); $customer_ids = $crm->getCustomerIDsByString($options['keywords'], true); if (count($customer_ids) > 0) { $stmt .= ' iss_customer_id IN (' . implode(', ', $customer_ids) . ')'; } else { // no results, kill query $stmt .= ' iss_customer_id = -1'; } } else { $stmt .= '(' . Misc::prepareBooleanSearch('iss_summary', $options['keywords']); $stmt .= ' OR ' . Misc::prepareBooleanSearch('iss_description', $options['keywords']) . ')'; } $stmt .= "\n) "; } if (!empty($options['customer_id'])) { $stmt .= " AND iss_customer_id='" . Misc::escapeString($options['customer_id']) . "'"; } if (!empty($options['priority'])) { $stmt .= ' AND iss_pri_id=' . Misc::escapeInteger($options['priority']); } if (!empty($options['status'])) { $stmt .= ' AND iss_sta_id=' . Misc::escapeInteger($options['status']); } if (!empty($options['category'])) { if (!is_array($options['category'])) { $options['category'] = array($options['category']); } $stmt .= ' AND iss_prc_id IN(' . implode(', ', Misc::escapeInteger($options['category'])) . ')'; } if (!empty($options['hide_closed'])) { $stmt .= ' AND sta_is_closed=0'; } if (!empty($options['release'])) { $stmt .= ' AND iss_pre_id = ' . Misc::escapeInteger($options['release']); } if (!empty($options['product'])) { $stmt .= ' AND ipv_pro_id = ' . Misc::escapeInteger($options['product']); } // now for the date fields $date_fields = array('created_date', 'updated_date', 'last_response_date', 'first_response_date', 'closed_date'); foreach ($date_fields as $field_name) { if (!empty($options[$field_name])) { switch ($options[$field_name]['filter_type']) { case 'greater': $stmt .= " AND iss_{$field_name} >= '" . Misc::escapeString($options[$field_name]['start']) . "'"; break; case 'less': $stmt .= " AND iss_{$field_name} <= '" . Misc::escapeString($options[$field_name]['start']) . "'"; break; case 'between': $stmt .= " AND iss_{$field_name} BETWEEN '" . Misc::escapeString($options[$field_name]['start']) . "' AND '" . Misc::escapeString($options[$field_name]['end']) . "'"; break; case 'null': $stmt .= " AND iss_{$field_name} IS NULL"; break; case 'in_past': if (strlen($options[$field_name]['time_period']) == 0) { $options[$field_name]['time_period'] = 0; } $stmt .= " AND (UNIX_TIMESTAMP('" . Date_Helper::getCurrentDateGMT() . "') - UNIX_TIMESTAMP(iss_{$field_name})) <= (" . Misc::escapeInteger($options[$field_name]['time_period']) . '*3600)'; break; } } } // custom fields if (is_array($options['custom_field']) && count($options['custom_field']) > 0) { foreach ($options['custom_field'] as $fld_id => $search_value) { if (empty($search_value)) { continue; } $field = Custom_Field::getDetails($fld_id); $fld_db_name = Custom_Field::getDBValueFieldNameByType($field['fld_type']); if ($field['fld_type'] == 'date' && (empty($search_value['Year']) || empty($search_value['Month']) || empty($search_value['Day']))) { continue; } if ($field['fld_type'] == 'integer' && empty($search_value['value'])) { continue; } if ($field['fld_type'] == 'multiple') { $search_value = Misc::escapeString($search_value); foreach ($search_value as $cfo_id) { $cfo_id = Misc::escapeString($cfo_id); $stmt .= " AND\n cf" . $fld_id . '_' . $cfo_id . '.icf_iss_id = iss_id'; $stmt .= " AND\n cf" . $fld_id . '_' . $cfo_id . ".icf_fld_id = {$fld_id}"; $stmt .= " AND\n cf" . $fld_id . '_' . $cfo_id . '.' . $fld_db_name . " = '{$cfo_id}'"; } } elseif ($field['fld_type'] == 'date') { if (empty($search_value['Year']) || empty($search_value['Month']) || empty($search_value['Day'])) { continue; } $search_value = $search_value['Year'] . '-' . $search_value['Month'] . '-' . $search_value['Day']; $stmt .= " AND\n (iss_id = cf" . $fld_id . '.icf_iss_id AND cf' . $fld_id . '.' . $fld_db_name . " = '" . Misc::escapeString($search_value) . "')"; } elseif ($field['fld_type'] == 'integer') { $value = $search_value['value']; switch ($search_value['filter_type']) { case 'ge': $cmp = '>='; break; case 'le': $cmp = '<='; break; case 'gt': $cmp = '>'; break; case 'lt': $cmp = '<'; break; default: $cmp = '='; break; } $stmt .= " AND\n (iss_id = cf" . $fld_id . '.icf_iss_id'; $stmt .= " AND\n cf" . $fld_id . ".icf_fld_id = {$fld_id}"; $stmt .= ' AND cf' . $fld_id . '.' . $fld_db_name . $cmp . Misc::escapeString($value) . ')'; } else { $stmt .= " AND\n (iss_id = cf" . $fld_id . '.icf_iss_id'; $stmt .= " AND\n cf" . $fld_id . ".icf_fld_id = {$fld_id}"; if ($field['fld_type'] == 'combo') { $stmt .= ' AND cf' . $fld_id . '.' . $fld_db_name . " IN('" . implode("', '", Misc::escapeString($search_value)) . "')"; } else { $stmt .= ' AND cf' . $fld_id . '.' . $fld_db_name . " LIKE '%" . Misc::escapeString($search_value) . "%'"; } $stmt .= ')'; } } } // clear cached full-text values if we are not searching fulltext anymore if (APP_ENABLE_FULLTEXT && @$options['search_type'] != 'all_text') { Session::set('fulltext_string', ''); Session::set('fulltext_issues', ''); } return $stmt; }
/** * Update SQL with common where clause * * @param string $sql * @param array $params * @param string $date_field * @param string $user_field */ private function createWhereClause(&$sql, &$params, $date_field, $user_field = null) { if ($this->report_type == 'recent') { $sql .= "{$date_field} >= DATE_SUB(?, INTERVAL ? {$this->unit})"; $params[] = Date_Helper::getCurrentDateGMT(); $params[] = $this->amount; } else { $sql .= "{$date_field} BETWEEN ? AND ?"; $params[] = $this->start_date; $params[] = $this->end_date; } if ($user_field && $this->developer) { $sql .= " AND {$user_field} = ?"; $params[] = $this->developer; } $sql .= " ORDER BY {$date_field} {$this->sort_order}"; }
/** * TODO: merge use of $options and $email arrays to just $email * * @param int $issue_id * @param string $type type of email * @param string $from * @param string $to * @param string $cc * @param string $subject * @param string $body * @param array $options optional parameters * - (int) parent_sup_id * - (array) iaf_ids attachment file ids * - (bool) add_unknown * - (int) ema_id * @return int 1 if it worked, -1 otherwise */ public static function sendEmail($issue_id, $type, $from, $to, $cc, $subject, $body, $options = array()) { $parent_sup_id = $options['parent_sup_id']; $iaf_ids = $options['iaf_ids']; $add_unknown = $options['add_unknown']; $ema_id = $options['ema_id']; $current_usr_id = Auth::getUserID(); $prj_id = Issue::getProjectID($issue_id); // if we are replying to an existing email, set the In-Reply-To: header accordingly $in_reply_to = $parent_sup_id ? self::getMessageIDByID($parent_sup_id) : false; // get ID of whoever is sending this. $sender_usr_id = User::getUserIDByEmail(Mail_Helper::getEmailAddress($from)) ?: false; // remove extra 'Re: ' from subject $subject = Mail_Helper::removeExcessRe($subject, true); $internal_only = false; $message_id = Mail_Helper::generateMessageID(); // process any files being uploaded // from ajax upload, attachment file ids if ($iaf_ids) { // FIXME: is it correct to use sender from post data? $attach_usr_id = $sender_usr_id ?: $current_usr_id; Attachment::attachFiles($issue_id, $attach_usr_id, $iaf_ids, false, 'Attachment originated from outgoing email'); } // hack needed to get the full headers of this web-based email $full_email = self::buildFullHeaders($issue_id, $message_id, $from, $to, $cc, $subject, $body, $in_reply_to, $iaf_ids); // email blocking should only be done if this is an email about an associated issue if ($issue_id) { $user_info = User::getNameEmail($current_usr_id); // check whether the current user is allowed to send this email to customers or not if (!self::isAllowedToEmail($issue_id, $user_info['usr_email'])) { // add the message body as a note $note = Mail_Helper::getCannedBlockedMsgExplanation() . $body; $note_options = array('full_message' => $full_email, 'is_blocked' => true); Note::insertNote($current_usr_id, $issue_id, $subject, $note, $note_options); $email_details = array('from' => $from, 'to' => $to, 'cc' => $cc, 'subject' => $subject, 'body' => &$body, 'message' => &$body, 'title' => $subject); Workflow::handleBlockedEmail($prj_id, $issue_id, $email_details, 'web'); return 1; } } // only send a direct email if the user doesn't want to add the Cc'ed people to the notification list if (($add_unknown || Workflow::shouldAutoAddToNotificationList($prj_id)) && $issue_id) { // add the recipients to the notification list of the associated issue $recipients = array($to); $recipients = array_merge($recipients, self::getRecipientsCC($cc)); foreach ($recipients as $address) { if ($address && !Notification::isIssueRoutingSender($issue_id, $address)) { $actions = Notification::getDefaultActions($issue_id, $address, 'add_unknown_user'); Notification::subscribeEmail($current_usr_id, $issue_id, Mail_Helper::getEmailAddress($address), $actions); } } } else { // Usually when sending out emails associated to an issue, we would // simply insert the email in the table and call the Notification::notifyNewEmail() method, // but on this case we need to actually send the email to the recipients that are not // already in the notification list for the associated issue, if any. // In the case of replying to an email that is not yet associated with an issue, then // we are always directly sending the email, without using any notification list // functionality. if ($issue_id) { // send direct emails only to the unknown addresses, and leave the rest to be // catched by the notification list $from = Notification::getFixedFromHeader($issue_id, $from, 'issue'); // build the list of unknown recipients if ($to) { $recipients = array($to); $recipients = array_merge($recipients, self::getRecipientsCC($cc)); } else { $recipients = self::getRecipientsCC($cc); } $unknowns = array(); foreach ($recipients as $address) { if (!Notification::isSubscribedToEmails($issue_id, $address)) { $unknowns[] = $address; } } if ($unknowns) { $to2 = array_shift($unknowns); $cc2 = implode('; ', $unknowns); // send direct emails self::sendDirectEmail($issue_id, $from, $to2, $cc2, $subject, $body, $_FILES['attachment'], $message_id, $sender_usr_id); } } else { // send direct emails to all recipients, since we don't have an associated issue $project_info = Project::getOutgoingSenderAddress(Auth::getCurrentProject()); // use the project-related outgoing email address, if there is one if (!empty($project_info['email'])) { $from = Mail_Helper::getFormattedName(User::getFullName($current_usr_id), $project_info['email']); } else { // otherwise, use the real email address for the current user $from = User::getFromHeader($current_usr_id); } // send direct emails self::sendDirectEmail($issue_id, $from, $to, $cc, $subject, $body, $_FILES['attachment'], $message_id); } } $email = array('customer_id' => 'NULL', 'issue_id' => $issue_id, 'ema_id' => $ema_id, 'message_id' => $message_id, 'date' => Date_Helper::getCurrentDateGMT(), 'from' => $from, 'to' => $to, 'cc' => $cc, 'subject' => $subject, 'body' => $body, 'full_email' => $full_email); // associate this new email with a customer, if appropriate if (Auth::getCurrentRole() == User::getRoleID('Customer')) { if ($issue_id) { $crm = CRM::getInstance($prj_id); try { $contact = $crm->getContact(User::getCustomerContactID($current_usr_id)); $issue_contract = $crm->getContract(Issue::getContractID($issue_id)); if ($contact->canAccessContract($issue_contract)) { $email['customer_id'] = $issue_contract->getCustomerID(); } } catch (CRMException $e) { } } else { $customer_id = User::getCustomerID($current_usr_id); if ($customer_id && $customer_id != -1) { $email['customer_id'] = $customer_id; } } } $email['has_attachment'] = $iaf_ids ? 1 : 0; $structure = Mime_Helper::decode($full_email, true, false); $email['headers'] = $structure->headers; self::insertEmail($email, $structure, $sup_id); if ($issue_id) { // need to send a notification Notification::notifyNewEmail($current_usr_id, $issue_id, $email, $internal_only, false, $type, $sup_id); // mark this issue as updated $has_customer = $email['customer_id'] && $email['customer_id'] != 'NULL'; if ($has_customer && (!$current_usr_id || User::getRoleByUser($current_usr_id, $prj_id) == User::getRoleID('Customer'))) { Issue::markAsUpdated($issue_id, 'customer action'); } else { if ($sender_usr_id && User::getRoleByUser($sender_usr_id, $prj_id) > User::getRoleID('Customer')) { Issue::markAsUpdated($issue_id, 'staff response'); } else { Issue::markAsUpdated($issue_id, 'user response'); } } History::add($issue_id, $current_usr_id, 'email_sent', 'Outgoing email sent by {user}', array('user' => User::getFullName($current_usr_id))); } return 1; }
/** * Converts a note to a draft or an email * * @param int $note_id The id of the note * @param string $target What the note should be converted too (email, etc) * @param bool $authorize_sender If $authorize_sender If the sender should be added to authorized senders list. * @return int */ public static function convertNote($note_id, $target, $authorize_sender = false) { $issue_id = self::getIssueID($note_id); $email_account_id = Email_Account::getEmailAccount(); $blocked_message = self::getBlockedMessage($note_id); $unknown_user = self::getUnknownUser($note_id); $structure = Mime_Helper::decode($blocked_message, true, true); $body = $structure->body; $sender_email = strtolower(Mail_Helper::getEmailAddress($structure->headers['from'])); $current_usr_id = Auth::getUserID(); if ($target == 'email') { if (Mime_Helper::hasAttachments($structure)) { $has_attachments = 1; } else { $has_attachments = 0; } list($blocked_message, $headers) = Mail_Helper::rewriteThreadingHeaders($issue_id, $blocked_message, @$structure->headers); $t = array('issue_id' => $issue_id, 'ema_id' => $email_account_id, 'message_id' => @$structure->headers['message-id'], 'date' => Date_Helper::getCurrentDateGMT(), 'from' => @$structure->headers['from'], 'to' => @$structure->headers['to'], 'cc' => @$structure->headers['cc'], 'subject' => @$structure->headers['subject'], 'body' => @$body, 'full_email' => @$blocked_message, 'has_attachment' => $has_attachments, 'headers' => $headers); // need to check for a possible customer association if (!empty($structure->headers['from'])) { $details = Email_Account::getDetails($email_account_id); // check from the associated project if we need to lookup any customers by this email address if (CRM::hasCustomerIntegration($details['ema_prj_id'])) { $crm = CRM::getInstance($details['ema_prj_id']); // check for any customer contact association try { $contact = $crm->getContactByEmail($sender_email); $issue_contract = $crm->getContract(Issue::getContractID($issue_id)); if ($contact->canAccessContract($issue_contract)) { $t['customer_id'] = $issue_contract->getCustomerID(); } } catch (CRMException $e) { } } } if (empty($t['customer_id'])) { $update_type = 'staff response'; $t['customer_id'] = null; } else { $update_type = 'customer action'; } $res = Support::insertEmail($t, $structure, $sup_id); if ($res != -1) { Support::extractAttachments($issue_id, $structure); // notifications about new emails are always external $internal_only = false; // special case when emails are bounced back, so we don't want to notify the customer about those if (Notification::isBounceMessage($sender_email)) { $internal_only = true; } Notification::notifyNewEmail($current_usr_id, $issue_id, $t, $internal_only, false, '', $sup_id); Issue::markAsUpdated($issue_id, $update_type); self::remove($note_id, false); History::add($issue_id, $current_usr_id, 'note_converted_email', 'Note converted to e-mail (from: {from}) by {user}', array('from' => @$structure->headers['from'], 'user' => User::getFullName($current_usr_id))); // now add sender as an authorized replier if ($authorize_sender) { Authorized_Replier::manualInsert($issue_id, @$structure->headers['from']); } } return $res; } // save message as a draft $res = Draft::saveEmail($issue_id, $structure->headers['to'], $structure->headers['cc'], $structure->headers['subject'], $body, false, $unknown_user); // remove the note, if the draft was created successfully if ($res) { self::remove($note_id, false); $usr_id = $current_usr_id; History::add($issue_id, $usr_id, 'note_converted_draft', 'Note converted to draft (from: {from}) by {user}', array('from' => @$structure->headers['from'], 'user' => User::getFullName($current_usr_id))); } return $res; }
/** * Saves a log entry about the attempt, successful or otherwise, to send the * queued email message. Also updates maq_status of $maq_id to $status. * * @param integer $maq_id The queued email message ID * @param string $status The status of the attempt ('sent' or 'error') * @param string $server_message The full message from the SMTP server, in case of an error * @return boolean */ private function _saveStatusLog($maq_id, $status, $server_message) { $stmt = 'INSERT INTO {{%mail_queue_log}} ( mql_maq_id, mql_created_date, mql_status, mql_server_message ) VALUES ( ?, ?, ?, ? )'; $params = array($maq_id, Date_Helper::getCurrentDateGMT(), $status, $server_message); try { DB_Helper::getInstance()->query($stmt, $params); } catch (DbException $e) { return false; } $stmt = 'UPDATE {{%mail_queue}} SET maq_status=? WHERE maq_id=?'; DB_Helper::getInstance()->query($stmt, array($status, $maq_id)); return true; }
/** * Method used to save a history entry about the execution of the current * reminder. * * @param integer $issue_id The issue ID * @param integer $rma_id The reminder action ID * @return boolean */ public function saveHistory($issue_id, $rma_id) { $stmt = 'INSERT INTO {{%reminder_history}} ( rmh_iss_id, rmh_rma_id, rmh_created_date ) VALUES ( ?, ?, ? )'; try { DB_Helper::getInstance()->query($stmt, array($issue_id, $rma_id, Date_Helper::getCurrentDateGMT())); } catch (DbException $e) { return false; } return true; }
/** * Returns the status of a quarantine. * * @param integer $issue_id The issue ID * @return integer Indicates what the current state of quarantine is. */ public static function getQuarantineInfo($issue_id) { $stmt = 'SELECT iqu_status, iqu_expiration FROM {{%issue_quarantine}} WHERE iqu_iss_id = ? AND (iqu_expiration > ? OR iqu_expiration IS NULL)'; try { $res = DB_Helper::getInstance()->getRow($stmt, array($issue_id, Date_Helper::getCurrentDateGMT())); } catch (DbException $e) { return array(); } if (!empty($res['iqu_expiration'])) { $expiration_ts = Date_Helper::getUnixTimestamp($res['iqu_expiration'], Date_Helper::getDefaultTimezone()); $res['time_till_expiration'] = Date_Helper::getFormattedDateDiff($expiration_ts, time()); } return $res; }
/** * Method used to update an existing draft response. * * @param integer $issue_id The issue ID * @param integer $emd_id The email draft ID * @param string $to The primary recipient of the draft * @param string $cc The secondary recipients of the draft * @param string $subject The subject of the draft * @param string $message The draft body * @param integer $parent_id The ID of the email that this draft is replying to, if any * @return integer 1 if the update worked, -1 otherwise */ public static function update($issue_id, $emd_id, $to, $cc, $subject, $message, $parent_id = null) { if (!$parent_id) { $parent_id = null; } $usr_id = Auth::getUserID(); // update previous draft and insert new record $stmt = "UPDATE\n {{%email_draft}}\n SET\n emd_updated_date=?,\n emd_status = 'edited'\n WHERE\n emd_id=?"; $params = array(Date_Helper::getCurrentDateGMT(), $emd_id); try { DB_Helper::getInstance()->query($stmt, $params); } catch (DbException $e) { return -1; } Issue::markAsUpdated($issue_id, 'draft saved'); History::add($issue_id, $usr_id, 'draft_updated', 'Email message draft updated by {user}', array('user' => User::getFullName($usr_id))); self::saveEmail($issue_id, $to, $cc, $subject, $message, $parent_id, false, false); return 1; }
/** * Method used to add a new resolution by using the administrative * interface of the system. * * @return integer 1 if the update worked, -1 or -2 otherwise */ public static function insert() { if (Validation::isWhitespace($_POST['title'])) { return -2; } $stmt = 'INSERT INTO {{%resolution}} ( res_title, res_rank, res_created_date ) VALUES ( ?, ?, ? )'; $params = array($_POST['title'], $_POST['rank'], Date_Helper::getCurrentDateGMT()); try { DB_Helper::getInstance()->query($stmt, $params); } catch (DbException $e) { return -1; } return 1; }
/** * Method used to add an attachment to the database. * * @param integer $issue_id The issue ID * @param integer $usr_id The user ID * @param string $description The description for this new attachment * @param boolean $internal_only Whether this attachment is supposed to be internal only or not * @param string $unknown_user The email of the user who originally sent this email, who doesn't have an account. * @param integer $associated_note_id The note ID that these attachments should be associated with * @return integer The new attachment ID */ public static function add($issue_id, $usr_id, $description, $internal_only = false, $unknown_user = null, $associated_note_id = null) { if ($internal_only) { $attachment_status = 'internal'; } else { $attachment_status = 'public'; } $params = array('iat_iss_id' => $issue_id, 'iat_usr_id' => $usr_id, 'iat_created_date' => Date_Helper::getCurrentDateGMT(), 'iat_description' => $description, 'iat_status' => $attachment_status); if ($unknown_user) { $params['iat_unknown_user'] = $unknown_user; } if ($associated_note_id) { $params['iat_not_id'] = $associated_note_id; } $stmt = 'INSERT INTO {{%issue_attachment}} SET ' . DB_Helper::buildSet($params); try { DB_Helper::getInstance()->query($stmt, $params); } catch (DbException $e) { return false; } return DB_Helper::get_last_insert_id(); }
/** * Method used to add a news entry to the system. * * @return integer 1 if the insert worked, -1 otherwise */ public static function insert() { if (Validation::isWhitespace($_POST['title'])) { return -2; } if (Validation::isWhitespace($_POST['message'])) { return -3; } $stmt = 'INSERT INTO {{%news}} ( nws_usr_id, nws_created_date, nws_title, nws_message, nws_status ) VALUES ( ?, ?, ?, ?, ? )'; $params = array(Auth::getUserID(), Date_Helper::getCurrentDateGMT(), $_POST['title'], $_POST['message'], $_POST['status']); try { DB_Helper::getInstance()->query($stmt, $params); } catch (DbException $e) { return -1; } $new_news_id = DB_Helper::get_last_insert_id(); // now populate the project-news mapping table foreach ($_POST['projects'] as $prj_id) { self::addProjectAssociation($new_news_id, $prj_id); } return 1; }
/** * Method used to remotely record a time tracking entry. * * @param integer $issue_id The issue ID * @param integer $usr_id The user ID * @param integer $cat_id The time tracking category ID * @param string $summary The summary of the work entry * @param integer $time_spent The time spent in minutes * @return integer 1 if the insert worked, -1 otherwise */ public static function recordRemoteTimeEntry($issue_id, $usr_id, $cat_id, $summary, $time_spent) { $stmt = 'INSERT INTO {{%time_tracking}} ( ttr_ttc_id, ttr_iss_id, ttr_usr_id, ttr_created_date, ttr_time_spent, ttr_summary ) VALUES ( ?, ?, ?, ?, ?, ? )'; $params = array($cat_id, $issue_id, $usr_id, Date_Helper::getCurrentDateGMT(), $time_spent, $summary); try { DB_Helper::getInstance()->query($stmt, $params); } catch (DbException $e) { return -1; } Issue::markAsUpdated($issue_id); History::add($issue_id, $usr_id, 'remote_time_added', 'Time tracking entry submitted remotely by {user}', array('user' => User::getFullName($usr_id))); return 1; }