<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 encoding=utf-8: */
// +----------------------------------------------------------------------+
// | Eventum - Issue Tracking System |
// +----------------------------------------------------------------------+
// | Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008 MySQL AB |
// | |
// | This program is free software; you can redistribute it and/or modify |
// | it under the terms of the GNU General Public License as published by |
// | the Free Software Foundation; either version 2 of the License, or |
// | (at your option) any later version. |
// | |
// | This program is distributed in the hope that it will be useful, |
// | but WITHOUT ANY WARRANTY; without even the implied warranty of |
// | 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. |
// | 59 Temple Place - Suite 330 |
// | Boston, MA 02111-1307, USA. |
// +----------------------------------------------------------------------+
// | Authors: João Prado Maia <hide@address.com> |
// +----------------------------------------------------------------------+
//
// @(#) $Id: class.command_line.php 3786 2008-12-02 17:08:25Z glen $
//
require_once(APP_INC_PATH . 'class.misc.php');
require_once(APP_PEAR_PATH . 'PEAR.php');
require_once(APP_PEAR_PATH . 'XML/RPC.php');
$_displayed_confirmation = false;
class Command_Line
{
/**
* Prompts the user for a resolution option, and returns the ID of the
* selected one.
*
* @access public
* @param resource $rpc_conn The connection resource
* @return integer The selected resolution id
*/
function promptResolutionSelection(&$rpc_conn)
{
$msg = new XML_RPC_Message("getResolutionAssocList");
$result = $rpc_conn->send($msg);
if ($result->faultCode()) {
Command_Line::quit($result->faultString());
}
$list = XML_RPC_decode($result->value());
if (count($list) > 1) {
// need to ask which status this person wants to use
$prompt = "Which resolution do you want to use in this action?\n";
foreach ($list as $key => $value) {
$prompt .= sprintf(" [%s] => %s\n", $key, $value);
}
$prompt .= "Please enter the resolution";
$resolution_id = Misc::prompt($prompt, false);
$available_ids = array_keys($list);
if (!in_array($resolution_id, $available_ids)) {
Command_Line::quit("Entered resolution doesn't match any in the list available to you");
}
} else {
if (count($list) == 0) {
$resolution_id = 0;
} else {
$t = array_keys($list);
$resolution_id = $t[0];
}
}
return $resolution_id;
}
/**
* Prompts the user for a status option, and returns the title of the
* selected one.
*
* @access public
* @param resource $rpc_conn The connection resource
* @param array $auth Array of authentication information (email, password)
* @param integer $prj_id The project ID
* @return string The selected status title
*/
function promptStatusSelection(&$rpc_conn, $auth, $prj_id)
{
$msg = new XML_RPC_Message("getClosedAbbreviationAssocList", array(new XML_RPC_Value($auth[0], 'string'), new XML_RPC_Value($auth[1], 'string'),
new XML_RPC_Value($prj_id, 'int')));
$result = $rpc_conn->send($msg);
if ($result->faultCode()) {
Command_Line::quit($result->faultString());
}
$list = XML_RPC_decode($result->value());
if (count($list) > 1) {
// need to ask which status this person wants to use
$prompt = "Which status do you want to use in this action?\n";
foreach ($list as $key => $value) {
$prompt .= sprintf(" [%s] => %s\n", $key, $value);
}
$prompt .= "Please enter the status";
$status = Misc::prompt($prompt, false);
$lowercase_keys = array_map('strtolower', array_keys($list));
$lowercase_values = array_map('strtolower', array_values($list));
if ((!in_array(strtolower($status), $lowercase_keys)) &&
(!in_array(strtolower($status), $lowercase_values))) {
Command_Line::quit("Entered status doesn't match any in the list available to you");
} else {
if (in_array(strtolower($status), $lowercase_keys)) {
$status_title = $list[strtoupper($status)];
} else {
$status_title = $status;
}
}
} else {
$t = array_values($list);
$status_title = $t[0];
}
return $status_title;
}
/**
* Marks an issue as closed.
*
* @access public
* @param resource $rpc_conn The connection resource
* @param array $auth Array of authentication information (email, password)
* @param integer $issue_id The issue ID
*/
function closeIssue(&$rpc_conn, $auth, $issue_id)
{
$details = Command_Line::checkIssuePermissions($rpc_conn, $auth, $issue_id);
Command_Line::checkIssueAssignment($rpc_conn, $auth, $issue_id);
// prompt for status selection (accept abbreviations)
$new_status = Command_Line::promptStatusSelection($rpc_conn, $auth, $details['iss_prj_id']);
// check if the issue already is set to the new status
if ((strtolower($details['sta_title']) == strtolower($new_status)) ||
(strtolower($details['sta_abbreviation']) == strtolower($new_status))) {
Command_Line::quit("Issue #$issue_id is already set to status '" . $details['sta_title'] . "'");
}
// prompt for status selection (accept abbreviations)
$resolution_id = Command_Line::promptResolutionSelection($rpc_conn);
// ask whether to send a notification email about this action or not (defaults to yes)
$msg = "Would you like to send a notification email about this issue being closed? [y/n]";
$ret = Misc::prompt($msg, false);
if (strtolower($ret) == 'y') {
$send_notification = true;
} else {
$send_notification = false;
}
// prompt for internal note
$prompt = "Please enter a reason for closing this issue (one line only)";
$note = Misc::prompt($prompt, false);
$params = array(
new XML_RPC_Value($auth[0], 'string'),
new XML_RPC_Value($auth[1], 'string'),
new XML_RPC_Value($issue_id, 'int'),
new XML_RPC_Value($new_status),
new XML_RPC_Value($resolution_id, 'int'),
new XML_RPC_Value($send_notification, 'boolean'),
new XML_RPC_Value($note)
);
$msg = new XML_RPC_Message("closeIssue", $params);
$result = $rpc_conn->send($msg);
if ($result->faultCode()) {
Command_Line::quit($result->faultString());
}
echo "OK - Issue #$issue_id successfully closed.\n";
if (XML_RPC_decode($result->value()) == 'INCIDENT') {
echo "WARNING: This customer has incidents. Please redeem incidents by running 'eventum $issue_id redeem'\n";
}
}
/**
* Looks up customer information given a set of search parameters.
*
* @access public
* @param resource $rpc_conn The connection resource
* @param array $auth Array of authentication information (email, password)
* @param string $field The field in which to search
* @param string $value The value to search against
*/
function lookupCustomer(&$rpc_conn, $auth, $field, $value)
{
$project_id = Command_Line::promptProjectSelection($rpc_conn, $auth, TRUE);
$params = array(
new XML_RPC_Value($auth[0], 'string'),
new XML_RPC_Value($auth[1], 'string'),
new XML_RPC_Value($project_id, 'int'),
new XML_RPC_Value($field),
new XML_RPC_Value($value)
);
$msg = new XML_RPC_Message("lookupCustomer", $params);
$result = $rpc_conn->send($msg);
if ($result->faultCode()) {
Command_Line::quit($result->faultString());
}
$res = XML_RPC_decode($result->value());
if (!is_array($res)) {
echo "ERROR: Sorry, for security reasons you need to wait $res until your next customer lookup.\n";
} else {
if (count($res) == 0) {
echo "Sorry, no customers could be found.\n";
} else {
$out = array();
$out[] = "Customer Lookup Results:\n";
foreach ($res as $customer) {
$out[] = ' Customer: ' . $customer['customer_name'];
$out[] = ' Support Level: ' . $customer['support_level'];
$out[] = ' Expiration: ' . $customer['expiration_date'];
$out[] = ' Contract Status: ' . $customer['contract_status'];
// contacts now...
if (count($customer['contacts']) > 0) {
$out[] = " Allowed Contacts: " . $customer['contacts'][0]['contact_name'] . ' - ' . $customer['contacts'][0]['email'] .
(empty($customer['contacts'][0]['phone']) ? '' : (' - ' . $customer['contacts'][0]['phone']));
for ($i = 1; $i < count($customer['contacts']); $i++) {
$out[] = " " . $customer['contacts'][$i]['contact_name'] . ' - ' . $customer['contacts'][$i]['email'] .
(empty($customer['contacts'][$i]['phone']) ? '' : (' - ' . $customer['contacts'][$i]['phone']));
}
}
$out[] = "\n";
}
echo implode("\n", $out);
}
}
}
/**
* Method used to parse the eventum command line configuration file
* and return the appropriate configuration settings.
*
* @access public
* @return array The configuration settings
*/
function getEnvironmentSettings()
{
$rcfile = getenv('HOME') . "/.eventumrc";
$email = '';
$password = '';
$host = '';
$port = '';
$relative_url = '';
if (file_exists($rcfile)) {
$fp = fopen($rcfile, 'r');
if (!$fp) {
die("Couldn't open eventum rcfile '$rcfile'\n");
}
$lines = explode("\n", fread($fp, filesize($rcfile)));
foreach ($lines as $line) {
$line = trim($line);
if (empty($line)) {
continue;
}
$var = trim(substr($line, 0, strpos($line, '=')));
$value = trim(substr($line, strpos($line, '=')+1));
if ($var == 'EVENTUM_USER') {
$email = $value;
} elseif ($var == 'EVENTUM_PASSWORD') {
$password = $value;
} elseif ($var == 'EVENTUM_HOST') {
$host = $value;
} elseif ($var == 'EVENTUM_PORT') {
$port = $value;
} elseif ($var == 'EVENTUM_RELATIVE_URL') {
$relative_url = $value;
}
}
} else {
die("Configuration file '$rcfile' could not be found\n");
}
return array($email, $password, $host, $port, $relative_url);
}
/**
* Prints out a list of attachments associated with the given issue ID.
*
* @access public
* @param resource $rpc_conn The connection resource
* @param array $auth Array of authentication information (email, password)
* @param integer $issue_id The issue ID
*/
function printFileList(&$rpc_conn, $auth, $issue_id)
{
Command_Line::checkIssuePermissions($rpc_conn, $auth, $issue_id);
$msg = new XML_RPC_Message("getFileList", array(new XML_RPC_Value($auth[0], 'string'), new XML_RPC_Value($auth[1], 'string'),
new XML_RPC_Value($issue_id, 'int')));
$result = $rpc_conn->send($msg);
if ($result->faultCode()) {
Command_Line::quit($result->faultString());
}
$list = XML_RPC_decode($result->value());
$i = 1;
foreach ($list as $attachment) {
echo "--------------------------------------------------------------\n";
echo " Attachment sent by " . $attachment['usr_full_name'] . " on " . $attachment['iat_created_date'] . "\n";
foreach ($attachment['files'] as $file) {
echo " [$i] => " . $file['iaf_filename'] . " (" . $file['iaf_filesize'] . ")\n";
$i++;
}
echo " Description: " . $attachment['iat_description'] . "\n";
}
}
/**
* Downloads a given attachment file number.
*
* @access public
* @param resource $rpc_conn The connection resource
* @param array $auth Array of authentication information (email, password)
* @param integer $issue_id The issue ID
* @param integer $file_number The attachment file number
*/
function getFile(&$rpc_conn, $auth, $issue_id, $file_number)
{
$details = Command_Line::checkIssuePermissions($rpc_conn, $auth, $issue_id);
// check if the provided file number is valid
$msg = new XML_RPC_Message("getFileList", array(new XML_RPC_Value($auth[0], 'string'), new XML_RPC_Value($auth[1], 'string'),
new XML_RPC_Value($issue_id, 'int')));
$result = $rpc_conn->send($msg);
if ($result->faultCode()) {
Command_Line::quit($result->faultString());
}
$list = XML_RPC_decode($result->value());
$file_id = 0;
$i = 1;
foreach ($list as $attachment) {
foreach ($attachment['files'] as $file) {
if ($file_number == $i) {
$file_id = $file['iaf_id'];
}
$i++;
}
}
if (empty($file_id)) {
Command_Line::quit("Unknown file number #$file_number. Please review the list of available files with 'list-files'");
}
echo "Downloading file #$file_number from issue $issue_id...\n";
$params = array(
new XML_RPC_Value($auth[0], 'string'),
new XML_RPC_Value($auth[1], 'string'),
new XML_RPC_Value($file_id, 'int')
);
$msg = new XML_RPC_Message("getFile", $params);
$result = $rpc_conn->send($msg);
if ($result->faultCode()) {
Command_Line::quit($result->faultString());
}
$details = XML_RPC_decode($result->value());
$details['iaf_file'] = base64_decode($details['iaf_file']);
// check if the file already exists
if (@file_exists($details['iaf_filename'])) {
$msg = "The requested file ('" . $details['iaf_filename'] . "') already exists in the current directory. Would you like to overwrite this file? [y/n]";
$ret = Misc::prompt($msg, false);
if (strtolower($ret) == 'y') {
@unlink($details['iaf_filename']);
if (@file_exists($details['iaf_filename'])) {
Command_Line::quit("No permission to remove the file");
}
} else {
Command_Line::quit("Download halted");
}
}
$fp = fopen($details['iaf_filename'], 'w');
fwrite($fp, $details['iaf_file']);
fclose($fp);
echo "OK - File '" . $details['iaf_filename'] . "' successfully downloaded to the local directory\n";
}
/**
* Checks whether the given user email address is assigned to the given
* issue ID.
*
* @access public
* @param resource $rpc_conn The connection resource
* @param array $auth Array of authentication information (email, password)
* @param integer $issue_id The issue ID
*/
function checkIssueAssignment(&$rpc_conn, $auth, $issue_id)
{
// check if the confirmation message was already displayed
if (!$GLOBALS['_displayed_confirmation']) {
// check if the current user is allowed to change the given issue
$msg = new XML_RPC_Message("mayChangeIssue", array(
new XML_RPC_Value($auth[0], 'string'),
new XML_RPC_Value($auth[1], 'string'),
new XML_RPC_Value($issue_id, 'int')
));
$result = $rpc_conn->send($msg);
if ($result->faultCode()) {
Command_Line::quit($result->faultString());
}
$may_change_issue = XML_RPC_decode($result->value());
// if not, show confirmation message
if ($may_change_issue != 'yes') {
echo "WARNING: You are not currently assigned to issue #$issue_id.\n";
Command_Line::promptConfirmation($rpc_conn, $auth, $issue_id, false);
}
}
}
/**
* Checks whether the given user email address is allowed to work with the
* given issue ID.
*
* @access public
* @param resource $rpc_conn The connection resource
* @param array $auth Array of authentication information (email, password)
* @param integer $issue_id The issue ID
* @param array The issue details, if the user is allowed to work on it
*/
function checkIssuePermissions(&$rpc_conn, $auth, $issue_id)
{
$projects = Command_Line::getUserAssignedProjects($rpc_conn, $auth);
$msg = new XML_RPC_Message("getIssueDetails", array(new XML_RPC_Value($auth[0], 'string'), new XML_RPC_Value($auth[1], 'string'),
new XML_RPC_Value($issue_id, 'int')));
$result = $rpc_conn->send($msg);
if ($result->faultCode()) {
Command_Line::quit($result->faultString());
}
$details = XML_RPC_decode($result->value());
foreach ($details as $k => $v) {
$details[$k] = base64_decode($v);
}
// check if the issue the user is trying to change is inside a project viewable to him
$found = 0;
for ($i = 0; $i < count($projects); $i++) {
if ($details['iss_prj_id'] == $projects[$i]['id']) {
$found = 1;
break;
}
}
if (!$found) {
Command_Line::quit("The assigned project for issue #$issue_id doesn't match any in the list of projects assigned to you");
}
return $details;
}
/**
* Method used to assign an issue to the current user.
*
* @access public
* @param resource $rpc_conn The connection resource
* @param array $auth Array of authentication information (email, password)
* @param integer $issue_id The issue ID
* @param string $developer The email address of the assignee
*/
function assignIssue(&$rpc_conn, $auth, $issue_id, $developer)
{
// check if the given email address is indeed an email
if (!strstr($developer, '@')) {
Command_Line::quit("The third argument for this command needs to be a valid email address");
}
$details = Command_Line::checkIssuePermissions($rpc_conn, $auth, $issue_id);
$params = array(
new XML_RPC_Value($auth[0], 'string'),
new XML_RPC_Value($auth[1], 'string'),
new XML_RPC_Value($issue_id, 'int'),
new XML_RPC_Value($details['iss_prj_id'], 'int'),
new XML_RPC_Value($developer)
);
$msg = new XML_RPC_Message("assignIssue", $params);
$result = $rpc_conn->send($msg);
if ($result->faultCode()) {
Command_Line::quit($result->faultString());
}
echo "OK - Issue #$issue_id successfully assigned to '$developer'\n";
}
/**
* Method used to assign an issue to the current user and set status to 'assigned'.
* If issue is already assigned to someone else, this will fail.
*
* @access public
* @param resource $rpc_conn The connection resource
* @param array $auth Array of authentication information (email, password)
* @param integer $issue_id The issue ID
*/
function takeIssue(&$rpc_conn, $auth, $issue_id)
{
$details = Command_Line::checkIssuePermissions($rpc_conn, $auth, $issue_id);
$params = array(
new XML_RPC_Value($auth[0], 'string'),
new XML_RPC_Value($auth[1], 'string'),
new XML_RPC_Value($issue_id, 'int'),
new XML_RPC_Value($details['iss_prj_id'], 'int'),
);
$msg = new XML_RPC_Message("takeIssue", $params);
$result = $rpc_conn->send($msg);
if ($result->faultCode()) {
Command_Line::quit($result->faultString());
}
echo "OK - Issue #$issue_id successfully taken.\n";
}
/**
* Method used to add an authorized replier
*
* @access public
* @param resource $rpc_conn The connection resource
* @param array $auth Array of authentication information (email, password)
* @param integer $issue_id The issue ID
* @param string $new_replier The email address of the assignee
*/
function addAuthorizedReplier(&$rpc_conn, $auth, $issue_id, $new_replier)
{
// check if the given email address is indeed an email
if (!strstr($new_replier, '@')) {
Command_Line::quit("The third argument for this command needs to be a valid email address");
}
$details = Command_Line::checkIssuePermissions($rpc_conn, $auth, $issue_id);
$params = array(
new XML_RPC_Value($auth[0], 'string'),
new XML_RPC_Value($auth[1], 'string'),
new XML_RPC_Value($issue_id, 'int'),
new XML_RPC_Value($details['iss_prj_id'], 'int'),
new XML_RPC_Value($new_replier)
);
$msg = new XML_RPC_Message("addAuthorizedReplier", $params);
$result = $rpc_conn->send($msg);
if ($result->faultCode()) {
Command_Line::quit($result->faultString());
}
echo "OK - '$new_replier' successfully added as an authorized replier to issue #$issue_id\n";
}
/**
* Method used to change the status of an issue.
*
* @access public
* @param resource $rpc_conn The connection resource
* @param array $auth Array of authentication information (email, password)
* @param integer $issue_id The issue ID
* @param string $new_status The new status title
*/
function setIssueStatus(&$rpc_conn, $auth, $issue_id, $new_status)
{
$details = Command_Line::checkIssuePermissions($rpc_conn, $auth, $issue_id);
Command_Line::checkIssueAssignment($rpc_conn, $auth, $issue_id);
// check if the issue already is set to the new status
if ((strtolower($details['sta_title']) == strtolower($new_status)) ||
(strtolower($details['sta_abbreviation']) == strtolower($new_status))) {
Command_Line::quit("Issue #$issue_id is already set to status '" . $details['sta_title'] . "'");
}
// check if the given status is a valid option
$msg = new XML_RPC_Message("getAbbreviationAssocList", array(
new XML_RPC_Value($auth[0], 'string'),
new XML_RPC_Value($auth[1], 'string'),
new XML_RPC_Value($details['iss_prj_id'], 'int'),
new XML_RPC_Value(FALSE, 'boolean'),
));
$result = $rpc_conn->send($msg);
if ($result->faultCode()) {
Command_Line::quit($result->faultString());
}
$statuses = XML_RPC_decode($result->value());
$titles = array_map('strtolower', array_values($statuses));
$abbreviations = array_map('strtolower', array_keys($statuses));
if ((!in_array(strtolower($new_status), $titles)) &&
(!in_array(strtolower($new_status), $abbreviations))) {
Command_Line::quit("Status '$new_status' could not be matched against the list of available statuses");
}
// if the user is passing an abbreviation, use the real title instead
if (in_array(strtolower($new_status), $abbreviations)) {
$index = array_search(strtolower($new_status), $abbreviations);
$new_status = $titles[$index];
}
$params = array(
new XML_RPC_Value($auth[0], 'string'),
new XML_RPC_Value($auth[1], 'string'),
new XML_RPC_Value($issue_id, 'int'),
new XML_RPC_Value($new_status)
);
$msg = new XML_RPC_Message("setIssueStatus", $params);
$result = $rpc_conn->send($msg);
if ($result->faultCode()) {
Command_Line::quit($result->faultString());
}
echo "OK - Status successfully changed to '$new_status' on issue #$issue_id\n";
}
/**
* Method used to add a time tracking entry to an existing issue.
*
* @access public
* @param resource $rpc_conn The connection resource
* @param array $auth Array of authentication information (email, password)
* @param integer $issue_id The issue ID
* @param string $time_spent The time spent in minutes
*/
function addTimeEntry(&$rpc_conn, $auth, $issue_id, $time_spent)
{
Command_Line::checkIssuePermissions($rpc_conn, $auth, $issue_id);
Command_Line::checkIssueAssignment($rpc_conn, $auth, $issue_id);
// list the time tracking categories
$msg = new XML_RPC_Message("getTimeTrackingCategories", array(new XML_RPC_Value($auth[0], 'string'), new XML_RPC_Value($auth[1], 'string')));
$result = $rpc_conn->send($msg);
if ($result->faultCode()) {
Command_Line::quit($result->faultString());
}
$cats = XML_RPC_decode($result->value());
$prompt = "Which time tracking category would you like to associate with this time entry?\n";
foreach ($cats as $id => $title) {
$prompt .= sprintf(" [%s] => %s\n", $id, $title);
}
$prompt .= "Please enter the number of the time tracking category";
$cat_id = Misc::prompt($prompt, false);
if (!in_array($cat_id, array_keys($cats))) {
Command_Line::quit("The selected time tracking category number didn't match any existing category");
}
$prompt = "Please enter a quick summary of what you worked on";
$summary = Misc::prompt($prompt, false);
$params = array(
new XML_RPC_Value($auth[0], 'string'),
new XML_RPC_Value($auth[1], 'string'),
new XML_RPC_Value($issue_id, 'int'),
new XML_RPC_Value($cat_id, 'int'),
new XML_RPC_Value($summary),
new XML_RPC_Value($time_spent, 'int')
);
$msg = new XML_RPC_Message("recordTimeWorked", $params);
$result = $rpc_conn->send($msg);
if ($result->faultCode()) {
Command_Line::quit($result->faultString());
}
echo "OK - Added time tracking entry to issue #$issue_id\n";
}
/**
* Method used to print the current details for a given issue.
*
* @access public
* @param resource $rpc_conn The connection resource
* @param array $auth Array of authentication information (email, password)
* @param integer $issue_id The issue ID
*/
function printIssueDetails(&$rpc_conn, $auth, $issue_id)
{
$details = Command_Line::checkIssuePermissions($rpc_conn, $auth, $issue_id);
$msg = '';
if (!empty($details["quarantine"]["iqu_status"])) {
$msg .= " WARNING: Issue is currently quarantined!";
if (!empty($details["quarantine"]["iqu_expiration"])) {
$msg .= " Quarantine expires in " . $details["quarantine"]["time_till_expiration"];
}
$msg .= "\n";
}
$msg .= " Issue #: $issue_id
Summary: " . $details['iss_summary'] . "
Status: " . $details['sta_title'] . "
Assignment: " . $details['assignments'] . "
Auth. Repliers: " . @implode(', ', $details['authorized_names']) . "
Reporter: " . $details['reporter'];
if (@isset($details['customer_info'])) {
$msg .= "
Customer: " . @$details['customer_info']['customer_name'] . "
Support Level: " . @$details['customer_info']['support_level'] . "
Support Options: " . @$details['customer_info']['support_options'] . "
Phone: " . $details['iss_contact_phone'] . "
Timezone: " . $details['iss_contact_timezone'] . "
Account Manager: " . @$details['customer_info']['account_manager'];
}
$msg .= "
Last Response: " . $details['iss_last_response_date'] . "
Last Updated: " . $details['iss_updated_date'] . "\n";
echo $msg;
}
/**
* Method used to print the list of open issues.
*
* @access public
* @param resource $rpc_conn The connection resource
* @param array $auth Array of authentication information (email, password)
* @param string $show_all_issues Whether to show all open issues or just the ones assigned to the current user
* @param string $status The status that should be used to restrict the results
*/
function printOpenIssues(&$rpc_conn, $auth, $show_all_issues, $status)
{
$project_id = Command_Line::promptProjectSelection($rpc_conn, $auth);
// check the status option
// check if the given status is a valid option
if (!empty($status)) {
$msg = new XML_RPC_Message("getAbbreviationAssocList", array(
new XML_RPC_Value($auth[0], 'string'),
new XML_RPC_Value($auth[1], 'string'),
new XML_RPC_Value($project_id, 'int'),
new XML_RPC_Value(TRUE, 'boolean'),
));
$result = $rpc_conn->send($msg);
if ($result->faultCode()) {
Command_Line::quit($result->faultString());
}
$statuses = XML_RPC_decode($result->value());
$titles = array_map('strtolower', array_values($statuses));
$abbreviations = array_map('strtolower', array_keys($statuses));
if ((!in_array(strtolower($status), $titles)) &&
(!in_array(strtolower($status), $abbreviations))) {
Command_Line::quit("Status '$status' could not be matched against the list of available statuses");
}
// if the user is passing an abbreviation, use the real title instead
if (in_array(strtolower($status), $abbreviations)) {
$status = $statuses[strtoupper($status)];
}
}
$msg = new XML_RPC_Message("getOpenIssues", array(
new XML_RPC_Value($auth[0], 'string'),
new XML_RPC_Value($auth[1], 'string'),
new XML_RPC_Value($project_id, 'int'),
new XML_RPC_Value($show_all_issues, 'boolean'),
new XML_RPC_Value($status)
));
$result = $rpc_conn->send($msg);
if ($result->faultCode()) {
Command_Line::quit($result->faultString());
}
$issues = XML_RPC_decode($result->value());
if (!empty($status)) {
echo "The following issues are set to status '$status':\n";
} else {
echo "The following issues are still open:\n";
}
foreach ($issues as $issue) {
echo "- #" . $issue['issue_id'] . " - " . $issue['summary'] . " (" . $issue['status'] . ")";
if (!empty($issue['assigned_users'])) {
echo " - (" . $issue['assigned_users'] . ")";
} else {
echo " - (unassigned)";
}
echo "\n";
}
}
/**
* Method used to get the list of projects assigned to a given email address.
*
* @access public
* @param resource $rpc_conn The connection resource
* @param array $auth Array of authentication information (email, password)
* @param boolean $only_customer_projects Whether to only include projects with customer integration or not
* @return array The list of projects
*/
function getUserAssignedProjects(&$rpc_conn, $auth, $only_customer_projects = FALSE)
{
$msg = new XML_RPC_Message("getUserAssignedProjects", array(
new XML_RPC_Value($auth[0], 'string'),
new XML_RPC_Value($auth[1], 'string'),
new XML_RPC_Value($only_customer_projects, 'boolean')
));
$result = $rpc_conn->send($msg);
if ($result->faultCode()) {
Command_Line::quit($result->faultString());
}
return XML_RPC_decode($result->value());
}
/**
* Method used to prompt the current user to select a project.
*
* @access public
* @param resource $rpc_conn The connection resource
* @param array $auth Array of authentication information (email, password)
* @param boolean $only_customer_projects Whether to only include projects with customer integration or not
* @return integer The project ID
*/
function promptProjectSelection(&$rpc_conn, $auth, $only_customer_projects = FALSE)
{
// list the projects that this user is assigned to
$projects = Command_Line::getUserAssignedProjects($rpc_conn, $auth, $only_customer_projects);
if (count($projects) > 1) {
// need to ask which project this person is asking about
$prompt = "For which project do you want this action to apply to?\n";
for ($i = 0; $i < count($projects); $i++) {
$prompt .= sprintf(" [%s] => %s\n", $projects[$i]['id'], $projects[$i]['title']);
}
$prompt .= "Please enter the number of the project";
$project_id = Misc::prompt($prompt, false);
$found = 0;
for ($i = 0; $i < count($projects); $i++) {
if ($project_id == $projects[$i]['id']) {
$found = 1;
break;
}
}
if (!$found) {
Command_Line::quit("Entered project number doesn't match any in the list of projects assigned to you");
}
} else {
$project_id = $projects[0]['id'];
}
return $project_id;
}
/**
* Method used to print the available statuses associated with the
* currently selected project.
*
* @access public
* @param resource $rpc_conn The connection resource
* @param array $auth Array of authentication information (email, password)
*/
function printStatusList(&$rpc_conn, $auth)
{
$project_id = Command_Line::promptProjectSelection($rpc_conn, $auth);
$msg = new XML_RPC_Message("getAbbreviationAssocList", array(
new XML_RPC_Value($auth[0], 'string'),
new XML_RPC_Value($auth[1], 'string'),
new XML_RPC_Value($project_id, 'int'),
new XML_RPC_Value(TRUE, 'boolean'),
));
$result = $rpc_conn->send($msg);
if ($result->faultCode()) {
Command_Line::quit($result->faultString());
}
$items = XML_RPC_decode($result->value());
echo "Available Statuses:\n";
foreach ($items as $abbreviation => $title) {
echo "$abbreviation => $title\n";
}
}
/**
* Method used to print the list of developers.
*
* @access public
* @param resource $rpc_conn The connection resource
* @param string $email The email address of the current user
*/
function printDeveloperList(&$rpc_conn, $auth)
{
$project_id = Command_Line::promptProjectSelection($rpc_conn, $auth);
$msg = new XML_RPC_Message("getDeveloperList", array(
new XML_RPC_Value($auth[0], 'string'),
new XML_RPC_Value($auth[1], 'string'),
new XML_RPC_Value($project_id, "int")
));
$result = $rpc_conn->send($msg);
if ($result->faultCode()) {
Command_Line::quit($result->faultString());
}
$developers = XML_RPC_decode($result->value());
echo "Available Developers:\n";
foreach ($developers as $name => $email) {
echo "-> $name - $email\n";
}
}
/**
* Method used to list emails for a given issue.
*
* @access public
* @param resource $rpc_conn The connection resource
* @param array $auth Array of authentication information (email, password)
* @param integer $issue_id The issue ID
*/
function listEmails(&$rpc_conn, $auth, $issue_id)
{
Command_Line::checkIssuePermissions($rpc_conn, $auth, $issue_id);
$msg = new XML_RPC_Message("getEmailListing", array(new XML_RPC_Value($auth[0], 'string'), new XML_RPC_Value($auth[1], 'string'),
new XML_RPC_Value($issue_id, "int")));
$result = $rpc_conn->send($msg);
if ($result->faultCode()) {
Command_Line::quit($result->faultString());
}
$emails = XML_RPC_decode($result->value());
if (!is_array($emails) || count($emails) < 1) {
echo "No emails for this issue";
exit;
}
// since xml-rpc has issues, we have to base64 decode everything
for ($i = 0; $i < count($emails); $i++) {
foreach ($emails[$i] as $key => $val) {
$emails[$i][$key] = base64_decode($val);
}
$emails[$i]["id"] = ($i+1);
}
$format = array(
"id" => array(
"width" => 3,
"title" => "ID"
),
"sup_date" => array(
"width" => 30,
"title" => "Date"
),
"sup_from" => array(
"width" => 24,
"title" => "From"
),
"sup_cc" => array(
"width" => 24,
"title" => "CC"
),
"sup_subject" => array(
"width" => 30,
"title" => "Subject"
)
);
Command_Line::printTable($format, $emails);
}
/**
* Method to show the contents of an email.
*
* @access public
* @param resource $rpc_conn The connection resource
* @param array $auth Array of authentication information (email, password)
* @param integer $issue_id The issue ID
* @param integer $email_id The sequential id of the email to view
* @param boolean $display_full If the full email should be displayed.
*/
function printEmail(&$rpc_conn, $auth, $issue_id, $email_id, $display_full)
{
Command_Line::checkIssuePermissions($rpc_conn, $auth, $issue_id);
$msg = new XML_RPC_Message("getEmail", array(new XML_RPC_Value($auth[0], 'string'), new XML_RPC_Value($auth[1], 'string'),
new XML_RPC_Value($issue_id, "int"), new XML_RPC_Value($email_id, "int")));
$result = $rpc_conn->send($msg);
if ($result->faultCode()) {
Command_Line::quit($result->faultString());
}
$email = XML_RPC_decode($result->value());
// since xml-rpc has issues, we have to base64 decode everything
foreach ($email as $key => $val) {
$email[$key] = base64_decode($val);
}
if ($display_full) {
echo $email["seb_full_email"];
} else {
echo sprintf("%15s: %s\n", "Date", $email["sup_date"]);
echo sprintf("%15s: %s\n", "From", $email["sup_from"]);
echo sprintf("%15s: %s\n", "To", $email["sup_to"]);
echo sprintf("%15s: %s\n", "CC", $email["sup_cc"]);
echo sprintf("%15s: %s\n", "Attachments?", (($email["sup_has_attachment"] == 1) ? 'yes' : 'no'));
echo sprintf("%15s: %s\n", "Subject", $email["sup_subject"]);
echo "------------------------------------------------------------------------\n";
echo $email["message"];
}
}
/**
* Method used to list notes for a given issue.
*
* @access public
* @param resource $rpc_conn The connection resource
* @param array $auth Array of authentication information (email, password)
* @param integer $issue_id The issue ID
*/
function listNotes(&$rpc_conn, $auth, $issue_id)
{
Command_Line::checkIssuePermissions($rpc_conn, $auth, $issue_id);
$msg = new XML_RPC_Message("getNoteListing", array(new XML_RPC_Value($auth[0], 'string'), new XML_RPC_Value($auth[1], 'string'),
new XML_RPC_Value($issue_id, "int")));
$result = $rpc_conn->send($msg);
if ($result->faultCode()) {
Command_Line::quit($result->faultString());
}
$notes = XML_RPC_decode($result->value());
// since xml-rpc has issues, we have to base64 decode everything
for ($i = 0; $i < count($notes); $i++) {
foreach ($notes[$i] as $key => $val) {
$notes[$i][$key] = base64_decode($val);
}
if ($notes[$i]["has_blocked_message"] == 1) {
$notes[$i]["not_title"] = '(BLOCKED) ' . $notes[$i]["not_title"];
}
$notes[$i]["id"] = ($i+1);
}
if (count($notes) < 1) {
echo "No notes for this issue";
exit;
}
$format = array(
"id" => array(
"width" => 3,
"title" => "ID"
),
"usr_full_name" => array(
"width" => 24,
"title" => "User"
),
"not_title" => array(
"width" => 50,
"title" => "Title"
),
"not_created_date" => array(
"width" => 30,
"title" => "Date"
)
);
Command_Line::printTable($format, $notes);
}
/**
* Method to show the contents of a note.
*
* @access public
* @param resource $rpc_conn The connection resource
* @param array $auth Array of authentication information (email, password)
* @param integer $issue_id The issue ID
* @param integer $note_id The sequential id of the note to view
*/
function printNote(&$rpc_conn, $auth, $issue_id, $note_id)
{
Command_Line::checkIssuePermissions($rpc_conn, $auth, $issue_id);
$note = Command_Line::getNote($rpc_conn, $auth, $issue_id, $note_id);
echo sprintf("%15s: %s\n", "Date", $note["not_created_date"]);
echo sprintf("%15s: %s\n", "From", $note["not_from"]);
echo sprintf("%15s: %s\n", "Title", $note["not_title"]);
echo "------------------------------------------------------------------------\n";
echo $note["not_note"];
}
/**
* Returns the contents of a note via XML-RPC.
*
* @access public
* @param resource $rpc_conn The connection resource
* @param array $auth Array of authentication information (email, password)
* @param integer $issue_id The issue ID
* @param integer $note_id The sequential id of the note to view
* @return array An array containg note details.
*/
function getNote(&$rpc_conn, $auth, $issue_id, $note_id)
{
$msg = new XML_RPC_Message("getNote", array(new XML_RPC_Value($auth[0], 'string'), new XML_RPC_Value($auth[1], 'string'),
new XML_RPC_Value($issue_id, "int"), new XML_RPC_Value($note_id, "int")));
$result = $rpc_conn->send($msg);
if ($result->faultCode()) {
Command_Line::quit($result->faultString());
}
$note = XML_RPC_decode($result->value());
// since xml-rpc has issues, we have to base64 decode everything
if (is_array($note)) {
foreach ($note as $key => $val) {
$note[$key] = base64_decode($val);
}
}
return $note;
}
/**
* Converts a note into a draft or an email.
*
* @access public
* @param resource $rpc_conn The connection source
* @param array $auth Array of authentication information (email, password)
* @param integer $issue_id The issue ID
* @param integer $note_id The sequential id of the note to view
* @param string $target What this note should be converted too, a draft or an email.
* @param boolean $authorize_sender If the sender should be added to the authorized repliers list.
*/
function convertNote(&$rpc_conn, $auth, $issue_id, $note_id, $target, $authorize_sender)
{
Command_Line::checkIssuePermissions($rpc_conn, $auth, $issue_id);
Command_Line::checkIssueAssignment($rpc_conn, $auth, $issue_id);
$note_details = Command_Line::getNote($rpc_conn, $auth, $issue_id, $note_id);
if (count($note_details) < 2) {
Command_Line::quit("Note #$note_id does not exist for issue #$issue_id");
} elseif ($note_details["has_blocked_message"] != 1) {
Command_Line::quit("Note #$note_id does not have a blocked message attached so cannot be converted");
}
$msg = new XML_RPC_Message("convertNote", array(
new XML_RPC_Value($auth[0], 'string'),
new XML_RPC_Value($auth[1], 'string'),
new XML_RPC_Value($issue_id, "int"),
new XML_RPC_Value($note_details["not_id"], "int"),
new XML_RPC_Value($target, "string"),
new XML_RPC_Value($authorize_sender, 'boolean')
));
$result = $rpc_conn->send($msg);
if ($result->faultCode()) {
Command_Line::quit($result->faultString());
}
$message = XML_RPC_decode($result->value());
if ($message == "OK") {
echo "OK - Note successfully converted to $target\n";
}
}
/**
* Fetches the weekly report for the current developer for the specified week.
*
* @access public
* @param resource $rpc_conn The connection resource
* @param array $auth Array of authentication information (email, password)
* @param integer $week The week for the report. If start and end date are set, this is ignored.
* @param string $start_date The start date of the report. (optional)
* @param string $end_date The end_date of the report. (optional)
* @param boolean If closed issues should be separated from other issues.
*/
function getWeeklyReport(&$rpc_conn, $auth, $week, $start_date = '', $end_date = '', $separate_closed = false)
{
$msg = new XML_RPC_Message("getWeeklyReport", array(
new XML_RPC_Value($auth[0], 'string'),
new XML_RPC_Value($auth[1], 'string'),
new XML_RPC_Value($week, "int"),
new XML_RPC_Value($start_date, "string"),
new XML_RPC_Value($end_date, "string"),
new XML_RPC_Value($separate_closed ? 1 : 0, 'int'),
));
$result = $rpc_conn->send($msg);
if ($result->faultCode()) {
Command_Line::quit($result->faultString());
} else {
$ret = XML_RPC_decode($result->value());
echo base64_decode($ret);
}
}
/**
* Clocks a user in/out of the system.
*
* @access public
* @param resource $rpc_conn The connection resource
* @param array $auth Array of authentication information (email, password)
* @param string $action If the user is clocking in or out.
*/
function timeClock(&$rpc_conn, $auth, $action)
{
$msg = new XML_RPC_Message("timeClock", array(
new XML_RPC_Value($auth[0], 'string'),
new XML_RPC_Value($auth[1], 'string'),
new XML_RPC_Value($action, "string")
));
$result = $rpc_conn->send($msg);
if ($result->faultCode()) {
Command_Line::quit($result->faultString());
} else {
echo XML_RPC_decode($result->value());
}
}
/**
* Lists drafts associated with an issue.
*
* @access public
* @param resource $rpc_conn The connection resource
* @param array $auth Array of authentication information (email, password)
* @param integer $issue_id The issue ID
*/
function listDrafts(&$rpc_conn, $auth, $issue_id)
{
Command_Line::checkIssuePermissions($rpc_conn, $auth, $issue_id);
$msg = new XML_RPC_Message("getDraftListing", array(new XML_RPC_Value($auth[0], 'string'), new XML_RPC_Value($auth[1], 'string'),
new XML_RPC_Value($issue_id, "int")));
$result = $rpc_conn->send($msg);
if ($result->faultCode()) {
Command_Line::quit($result->faultString());
}
$drafts = XML_RPC_decode($result->value());
// since xml-rpc has issues, we have to base64 decode everything
for ($i = 0; $i < count($drafts); $i++) {
foreach ($drafts[$i] as $key => $val) {
$drafts[$i][$key] = base64_decode($val);
}
$drafts[$i]["id"] = ($i+1);
}
if (count($drafts) < 1) {
echo "No drafts for this issue";
exit;
}
$format = array(
"id" => array(
"width" => 3,
"title" => "ID"
),
"from" => array(
"width" => 24,
"title" => "From"
),
"to" => array(
"width" => 24,
"title" => "To"
),
"emd_subject" => array(
"width" => 30,
"title" => "Title"
),
"emd_updated_date" => array(
"width" => 30,
"title" => "Date"
)
);
Command_Line::printTable($format, $drafts);
}
/**
* Method to show the contents of a draft.
*
* @access public
* @param resource $rpc_conn The connection resource
* @param array $auth Array of authentication information (email, password)
* @param integer $issue_id The issue ID
* @param integer $note_id The sequential id of the draft to view
*/
function printDraft(&$rpc_conn, $auth, $issue_id, $draft_id)
{
Command_Line::checkIssuePermissions($rpc_conn, $auth, $issue_id);
$draft = Command_Line::getDraft($rpc_conn, $auth, $issue_id, $draft_id);
echo sprintf("%15s: %s\n", "Date", $draft["emd_updated_date"]);
echo sprintf("%15s: %s\n", "From", $draft["from"]);
echo sprintf("%15s: %s\n", "To", $draft["to"]);
if (!empty($draft['cc'])) {
echo sprintf("%15s: %s\n", "Cc", $draft["cc"]);
}
echo sprintf("%15s: %s\n", "Title", $draft["emd_subject"]);
echo "------------------------------------------------------------------------\n";
echo $draft["emd_body"];
}
/**
* Returns the contents of a draft via XML-RPC.
*
* @access public
* @param resource $rpc_conn The connection resource
* @param array $auth Array of authentication information (email, password)
* @param integer $issue_id The issue ID
* @param integer $draft_id The sequential id of the draft to view
* @return array An array containg draft details.
*/
function getDraft(&$rpc_conn, $auth, $issue_id, $draft_id)
{
$msg = new XML_RPC_Message("getDraft", array(new XML_RPC_Value($auth[0], 'string'), new XML_RPC_Value($auth[1], 'string'),
new XML_RPC_Value($issue_id, "int"), new XML_RPC_Value($draft_id, "int")));
$result = $rpc_conn->send($msg);
if ($result->faultCode()) {
Command_Line::quit($result->faultString());
}
$draft = XML_RPC_decode($result->value());
// since xml-rpc has issues, we have to base64 decode everything
if (is_array($draft)) {
foreach ($draft as $key => $val) {
$draft[$key] = base64_decode($val);
}
}
return $draft;
}
/**
* Converts a draft to an email and sends it.
*
* @access public
* @param resource $rpc_conn The connection resource
* @param array $auth Array of authentication information (email, password)
* @param integer $issue_id The issue ID
* @param integer $draft_id The sequential id of the draft to send
* @return array An array containg draft details.
*/
function sendDraft(&$rpc_conn, $auth, $issue_id, $draft_id)
{
$msg = new XML_RPC_Message("sendDraft", array(new XML_RPC_Value($auth[0], 'string'), new XML_RPC_Value($auth[1], 'string'),
new XML_RPC_Value($issue_id, "int"), new XML_RPC_Value($draft_id, "int")));
$result = $rpc_conn->send($msg);
if ($result->faultCode()) {
Command_Line::quit($result->faultString());
}
echo XML_RPC_decode($result->value());
}
/**
* Marks an issue as redeemed incident
*
* @access public
* @param resource $rpc_conn The connection resource
* @param array $auth Array of authentication information (email, password)
* @param integer $issue_id The issue ID
*/
function redeemIssue(&$rpc_conn, $auth, $issue_id)
{
Command_Line::checkIssuePermissions($rpc_conn, $auth, $issue_id);
Command_Line::checkIssueAssignment($rpc_conn, $auth, $issue_id);
$types = Command_Line::promptIncidentTypes($rpc_conn, $auth, $issue_id);
foreach ($types as $type_id => $type_value) {
$types[$type_id] = new XML_RPC_Value($type_value, 'string');
}
$params = array(
new XML_RPC_Value($auth[0], 'string'),
new XML_RPC_Value($auth[1], 'string'),
new XML_RPC_Value($issue_id, 'int'),
new XML_RPC_Value($types, 'struct')
);
$msg = new XML_RPC_Message("redeemIssue", $params);
$result = $rpc_conn->send($msg);
if ($result->faultCode()) {
Command_Line::quit($result->faultString());
}
echo "OK - Issue #$issue_id successfully marked as redeemed incident.\n";
}
/**
* Un-marks an issue as redeemed incident
*
* @access public
* @param resource $rpc_conn The connection resource
* @param array $auth Array of authentication information (email, password)
* @param integer $issue_id The issue ID
*/
function unredeemIssue(&$rpc_conn, $auth, $issue_id)
{
Command_Line::checkIssuePermissions($rpc_conn, $auth, $issue_id);
Command_Line::checkIssueAssignment($rpc_conn, $auth, $issue_id);
$types = Command_Line::promptIncidentTypes($rpc_conn, $auth, $issue_id, true);
foreach ($types as $type_id => $type_value) {
$types[$type_id] = new XML_RPC_Value($type_value, 'string');
}
$params = array(
new XML_RPC_Value($auth[0], 'string'),
new XML_RPC_Value($auth[1], 'string'),
new XML_RPC_Value($issue_id, 'int'),
new XML_RPC_Value($types, 'struct')
);
$msg = new XML_RPC_Message("unredeemIssue", $params);
$result = $rpc_conn->send($msg);
if ($result->faultCode()) {
Command_Line::quit($result->faultString());
}
echo "OK - Issue #$issue_id successfully marked as unredeemed incident.\n";
}
/**
* Returns the list of incident types available.
*
* @access public
* @param resource $rpc_conn The connection resource
* @param array $auth Array of authentication information (email, password)
* @param integer $issue_id The issue ID
* @param boolean $redeemed_only If this should only show items that have been redeemed.
*/
function promptIncidentTypes(&$rpc_conn, $auth, $issue_id, $redeemed_only = false)
{
$params = array(
new XML_RPC_Value($auth[0], 'string'),
new XML_RPC_Value($auth[1], 'string'),
new XML_RPC_Value($issue_id, 'int'),
new XML_RPC_Value($redeemed_only, 'boolean')
);
$msg = new XML_RPC_Message("getIncidentTypes", $params);
$result = $rpc_conn->send($msg);
if ($result->faultCode()) {
Command_Line::quit($result->faultString());
}
$types = XML_RPC_decode($result->value());
if (count($types) < 1) {
if ($redeemed_only) {
Command_Line::quit("No incident types have been redeemed for this issue");
} else {
Command_Line::quit("All incident types have already been redeemed for this issue");
}
}
$prompt = "Please enter a comma seperated list of incident types to ";
if ($redeemed_only) {
$prompt .= "un";
}
$prompt .= "redeem for this issue.\n";
foreach ($types as $id => $data) {
$prompt .= sprintf(" [%s] => %s (Total: %s; Left: %s)\n", $id, $data['title'], $data['total'], ($data['total'] - $data['redeemed']));
}
$requested_types = Misc::prompt($prompt, false);
$requested_types = explode(',', $requested_types);
if (count($requested_types) < 1) {
Command_Line::quit("Please enter a comma seperated list of issue types");
} else {
$type_keys = array_keys($types);
foreach ($requested_types as $type_id) {
if (!in_array($type_id, $type_keys)) {
Command_Line::quit("Input '$type_id' is not a valid incident type");
}
}
return $requested_types;
}
}
/**
* Method to print data in a formatted table, according to the $format array.
*
* @param array $format An array containing how to format the data
* @param array $data An array of data to be printed
*/
function printTable($format, $data)
{
// loop through the fields, printing out the header row
$firstRow = '';
$secondRow = '';
foreach ($format as $column) {
$firstRow .= sprintf("%-" . $column["width"] . "s", $column["title"]) . " ";
$secondRow .= sprintf("%-'-" . $column["width"] . "s","") . " ";
}
echo $firstRow . "\n" . $secondRow . "\n";
// print out data
for ($i = 0; $i < count($data); $i++) {
foreach ($format as $key => $column) {
echo sprintf("%-" . $column["width"] . "s", substr($data[$i][$key], 0, $column["width"])) . " ";
}
echo "\n";
}
}
/**
* Method used to print a confirmation prompt with the current details
* of the given issue. The $command parameter can be used to determine what type of
* confirmation to show to the user.
*
* @access public
* @param resource $rpc_conn The connection resource
* @param array $auth Array of authentication information (email, password)
* @param integer $issue_id The issue ID
* @param string $args The arguments passed to this script
*/
function promptConfirmation(&$rpc_conn, $auth, $issue_id, $args)
{
// this is needed to prevent multiple confirmations from being shown to the user
$GLOBALS['_displayed_confirmation'] = true;
// get summary, customer status and assignment of issue, then show confirmation prompt to user
$msg = new XML_RPC_Message("getSimpleIssueDetails", array(new XML_RPC_Value($auth[0], 'string'), new XML_RPC_Value($auth[1], 'string'),
new XML_RPC_Value($issue_id, "int")));
$result = $rpc_conn->send($msg);
if ($result->faultCode()) {
Command_Line::quit($result->faultString());
} else {
switch ($args[2]) {
case 'convert-note':
case 'cn':
$note_details = Command_Line::getNote($rpc_conn, $auth, $issue_id, $args[3]);
$msg = "These are the current details for issue #$issue_id, note #" . $args[3] . ":\n" .
" Date: " . $note_details["not_created_date"] . "\n" .
" From: " . $note_details["not_from"] . "\n" .
" Title: " . $note_details["not_title"] . "\n" .
"Are you sure you want to convert this note into a " . $args[4] . "?";
break;
default:
$details = XML_RPC_decode($result->value());
$msg = "These are the current details for issue #$issue_id:\n" .
" Summary: " . $details['summary'] . "\n";
if (@!empty($details['customer'])) {
$msg .= " Customer: " . $details['customer'] . "\n";
}
$msg .= " Status: " . $details['status'] . "\n" .
" Assignment: " . $details["assignments"] . "\n" .
" Auth. Repliers: " . $details["authorized_names"] . "\n" .
"Are you sure you want to change this issue?";
}
$ret = Misc::prompt($msg, 'y');
if (strtolower($ret) != 'y') {
exit;
}
}
}
/**
* Method used to check the authentication of the current user.
*
* @access public
* @param resource $rpc_conn The connection resource
* @param string $email The email address of the current user
* @param string $password The password of the current user
*/
function checkAuthentication(&$rpc_conn, $email, $password)
{
$msg = new XML_RPC_Message("isValidLogin", array(new XML_RPC_Value($email), new XML_RPC_Value($password)));
$result = $rpc_conn->send($msg);
if (!is_object($result)) {
Command_Line::quit("result is not an object. This is most likely due connection problems or openssl/curl extension not loaded.");
}
if ($result->faultCode()) {
Command_Line::quit($result->faultString());
}
$is_valid = XML_RPC_Decode($result->value());
if ($is_valid != 'yes') {
Command_Line::quit("Login information could not be authenticated");
}
}
/**
* Logs the current command
*
* @access public
* @param resource $rpc_conn The connection resource
* @param array $auth Array of authentication information (email, password)
* @param string $command The command used to run this script.
*/
function log(&$rpc_conn, $auth, $command)
{
$command = base64_encode($command);
$msg = new XML_RPC_Message("logCommand", array(new XML_RPC_Value($auth[0], 'string'), new XML_RPC_Value($auth[1], 'string'), new XML_RPC_Value($command, 'string')));
$result = $rpc_conn->send($msg);
if ($result->faultCode()) {
Command_Line::quit($result->faultString());
}
}
/**
* Method used to check whether the current execution needs to have a
* confirmation message shown before performing the requested action or not.
*
* @access public
* @return boolean
*/
function isSafeExecution()
{
global $argv, $argc;
if ($argv[count($argv) - 1] == '--safe') {
array_pop($argv);
return true;
} else {
return false;
}
}
/**
* Method used to print a usage statement for the command line interface.
*
* @access public
* @param string $script The current script name
*/
function usage($script)
{
$usage = array();
$usage[] = array(
"command" => "<ticket_number>",
"help" => "View general details of an existing issue."
);
$usage[] = array(
"command" => "<ticket_number> assign <developer_email> [--safe]",
"help" => "Assign an issue to another developer."
);
$usage[] = array(
"command" => "<ticket_number> take [--safe]",
"help" => "Assign an issue to yourself and change status to 'Assigned'."
);
$usage[] = array(
"command" => array("<ticket_number> add-replier <user_email> [--safe]","<ticket_number> ar <user_email> [--safe]"),
"help" => "Adds the specified user to the list of authorized repliers."
);
$usage[] = array(
"command" => "<ticket_number> set-status <status> [--safe]",
"help" => "Sets the status of an issue to the desired value. If you are not sure
about the available statuses, use command 'list-status' described below."
);
$usage[] = array(
"command" => "<ticket_number> add-time <time_worked> [--safe]",
"help" => "Records time worked to the time tracking tool of the given issue."
);
$usage[] = array(
"command" => "<ticket_number> close [--safe]",
"help" => "Marks an issue as closed."
);
$usage[] = array(
"command" => array("<ticket_number> list-files", "<ticket_number> lf"),
"help" => "List available attachments associated with the given issue.",
);
$usage[] = array(
"command" => array("<ticket_number> get-file <file_number>", "<ticket_number> gf <file_number>"),
"help" => "Download a specific file from the given issue."
);
$usage[] = array(
"command" => array("<ticket_number> list-emails","<ticket_number> le"),
"help" => "Lists emails from the given issue."
);
$usage[] = array(
"command" => array("<ticket_number> get-email <email_number> [--full]","<ticket_number> ge <email_number> [--full]"),
"help" => "Displays a specific email for the issue. If the optional --full parameter
is specified, the full email including headers and attachments will be
displayed."
);
$usage[] = array(
"command" => array("<ticket_number> list-notes","<ticket_number> ln"),
"help" => "Lists notes from the given issue."
);
$usage[] = array(
"command" => array("<ticket_number> get-note <note_number> [--full]","<ticket_number> gn <note_number>"),
"help" => "Displays a specific note for the issue."
);
$usage[] = array(
"command" => array("<ticket_number> convert-note <note_number> draft|email [authorize] [--safe]","<ticket_number> cn <note_number> draft|email [authorize] [--safe]"),
"help" => "Converts the specified note to a draft or an email.
Use optional argument 'authorize' to add sender to authorized repliers list."
);
$usage[] = array(
"command" => array("<ticket_number> list-drafts","<ticket_number> ld"),
"help" => "Lists drafts from the given issue."
);
$usage[] = array(
"command" => array("<ticket_number> get-draft <draft_number>","<ticket_number> gd <draft_number>"),
"help" => "Displays a specific draft for the issue."
);
$usage[] = array(
"command" => array("<ticket_number> send-draft <draft_number>","<ticket_number> sd <draft_number>"),
"help" => "Converts a draft to an email and sends it out."
);
$usage[] = array(
"command" => array("<ticket_number> redeem"),
"help" => "Marks an issue as redeemed incident."
);
$usage[] = array(
"command" => array("<ticket_number> unredeem"),
"help" => "Un-marks an issue as redeemed incident."
);
$usage[] = array(
"command" => "developers",
"help" => "List all available developers' email addresses."
);
$usage[] = array(
"command" => "open-issues [<status>] [my]",
"help" => "List all issues that are not set to a status with a 'closed' context. Use
optional argument 'my' if you just wish to see issues assigned to you."
);
$usage[] = array(
"command" => "list-status",
"help" => "List all available statuses in the system."
);
$usage[] = array(
"command" => "customer email|support|customer <value>",
"help" => "Looks up a customer's record information."
);
$usage[] = array(
"command" => array("weekly-report ([<week>] [--separate-closed])|([<start>] [<end>] [--separate-closed])", "wr ([<week>])|([<start>] [<end>] [--separate-closed])"),
"help" => "Fetches the weekly report. Week is specified as an integer with 0 representing
the current week, -1 the previous week and so on. If the week is omitted it defaults
to the current week. Alternately, a date range can be set. Dates should be in the format 'YYYY-MM-DD'."
);
$usage[] = array(
"command" => "clock [in|out]",
"help" => "Clocks you in or out of the system. When clocked out, no reminders will be sent to your account.
If the in|out parameter is left off, your current status is displayed."
);
$script = basename($script);
$usage_text = "";
$explanation = "";
foreach ($usage as $command_num => $this_command) {
$item_num = sprintf("%2d.) ", ($command_num+1));
$usage_text .= $item_num . "$script ";
if (is_array($this_command["command"])) {
for ($i = 0; $i < count($this_command["command"]); $i++) {
if ($i != 0) {
$usage_text .= " $script ";
}
$usage_text .= $this_command["command"][$i] . "\n";
}
} else {
$usage_text .= $this_command["command"] . "\n";
}
$explanation .= $item_num . $this_command["help"] . "\n\n";
}
echo "
General Usage:
$usage_text
Explanations:
$explanation";
exit;
}
/**
* Method used to print a message to standard output and halt processing.
*
* @access public
* @param string $msg The message that needs to be printed
*/
function quit($msg)
{
die("Error - $msg. Run script with --help for usage information.\n");
}
}
// benchmarking the included file (aka setup time)
if (APP_BENCHMARK) {
$GLOBALS['bench']->setMarker('Included Command_Line Class');
}