'status', 'pri' => 'priority', 'id' => 'ticket', 'type' => 'classification', ); $supported_fields = array( 'classification', 'ticket', 'milestone', '-milestone', '+milestone', 'summary', 'status', 'priority', 'owner', 'type', 'component', '-component', '+component', 'description' ); foreach ($supported_fields as $i => $f) { unset($supported_fields[$i]); $supported_fields[$f] = $f; } $C = MTrackTicket_CustomFields::getInstance(); foreach ($C->fields as $f) { $name = substr($f->name, 2); $supported_fields[$f->name] = $f->name; if (!isset($field_aliases[$name])) { $field_aliases[$name] = $f->name; } } if ($_SERVER['REQUEST_METHOD'] == 'POST') { if (isset($_FILES['csvfile']) && $_FILES['csvfile']['error'] == 0 && is_uploaded_file($_FILES['csvfile']['tmp_name'])) { ini_set('auto_detect_line_endings', true); $fp = fopen($_FILES['csvfile']['tmp_name'], 'r'); $header = fgetcsv($fp); $err = array(); $output = array(); foreach ($header as $i => $name) { $name = strtolower($name); if (isset($field_aliases[$name])) { $name = $field_aliases[$name]; } if (!isset($supported_fields[$name])) { $err[] = "Unsupported field: $name"; } $header[$i] = $name; } $db = MTrackDB::get(); $db->beginTransaction(); MTrackChangeset::$use_txn = false; $todo = array(); do { $line = fgetcsv($fp); if ($line === false) break; $item = array(); foreach ($header as $i => $name) { $item[$name] = $line[$i]; } if (isset($item['ticket'])) { $id = $item['ticket']; if ($id[0] == '#') { $id = substr($id, 1); } try { $tkt = MTrackIssue::loadByNSIdent($id); if ($tkt == null) { $err[] = "No such ticket $id"; continue; } } catch (Exception $e) { $err[] = $e->getMessage(); continue; } $output[] = "Updating ticket $tkt->nsident
\n"; } else { $tkt = new MTrackIssue; $tkt->priority = 'normal'; list($tkt->nsident) = MTrackDB::q( 'select max(cast(nsident as integer)) + 1 from tickets') ->fetchAll(PDO::FETCH_COLUMN, 0); if ($tkt->nsident === null) { $tkt->nsident = 1; } $output[] = "Creating ticket $tkt->nsident
\n"; } $CS = MTrackChangeset::begin("ticket:X", $_POST['comment']); if (strlen(trim($_POST['comment']))) { $tkt->addComment($_POST['comment']); } foreach ($item as $name => $value) { if ($name == 'ticket') { continue; } $output[] = "$name => $value
\n"; try { switch ($name) { case 'summary': case 'description': case 'classification': case 'priority': case 'severity': case 'changelog': case 'owner': case 'cc': $tkt->$name = strlen($value) ? $value : null; break; case 'milestone': if (strlen($value)) { foreach ($tkt->getMilestones() as $mid) { $tkt->dissocMilestone($mid); } $tkt->assocMilestone($value); } break; case '+milestone': if (strlen($value)) { $tkt->assocMilestone($value); } break; case '-milestone': if (strlen($value)) { $tkt->dissocMilestone($value); } break; case 'component': if (strlen($value)) { foreach ($tkt->getComponents() as $mid) { $tkt->dissocComponent($mid); } $tkt->assocComponent($value); } break; case '+component': if (strlen($value)) { $tkt->assocComponent($value); } break; case '-component': if (strlen($value)) { $tkt->dissocComponent($value); } break; default: if (!strncmp($name, 'x_', 2)) { $tkt->{$name} = $value; } break; } } catch (Exception $e) { $err[] = $e->getMessage(); } } $tkt->save($CS); $CS->setObject("ticket:" . $tkt->tid); } while (true); $_SESSION['admin.import.result'] = array($err, $output); if (count($err)) { $db->rollback(); } else { $db->commit(); } } header("Location: {$ABSWEB}admin/importcsv.php"); exit; } if (isset($_SESSION['admin.import.result'])) { list($err, $info) = $_SESSION['admin.import.result']; unset($_SESSION['admin.import.result']); mtrack_head(count($err) ? 'Import Failed' : 'Import Complete'); foreach ($info as $line) { echo $line; } if (count($err)) { echo "The following errors were encountered:
\n"; foreach ($err as $msg) { echo htmlentities($msg) . "
\n"; } echo "
No changes were committed
\n"; } else { echo "
Done!\n"; } mtrack_foot(); exit; } mtrack_head('Import'); ?>

Import/Update via CSV

You may use this facility to change ticket properties en-masse by uploading a CSV file.

The input file must be a CSV file with the field names on the first line.

The following fields are supported:

ticket
The ticket number
milestone
The value to use for the milestone. If updating an existing ticket, this field will remove any other milestones in the ticket and set it to only this value.
-milestone
Removes a milestone; if the ticket is associated with the named milestone, it will be removed from that milestone.
+milestone
Associates the ticket with the named milestone, preserving any other milestones currently associated with the ticket.
summary
Sets the summary for the ticket
status or state
Sets the state of the ticket; can be one of the configured ticket states
priority
Sets the priority; can be one of the configured priorities
owner
Sets the owner
type
Sets the ticket type
component
Sets the component, replacing all other component associations
-component
Removes association with the named component
+component
Associates with the named component, preserving existing associations
description
Sets the description of the ticket
fields as $f) { $name = substr($f->name, 2); if (!isset($field_aliases[$name]) || $field_aliases[$name] != $f->name) { $name = $f->name; echo "
$name
\n"; } else { echo "
$name
\n"; echo "
$f->name
\n"; } echo "
" . htmlentities($f->label, ENT_QUOTES, 'utf-8') . "\n"; if ($f->type == 'select') { echo "
Value may be one of:
"; $data = $f->ticketData(); foreach ($data['options'] as $opt) { echo " " . htmlentities($opt, ENT_QUOTES, 'utf-8') . "
"; } } echo "
\n"; } ?>

Import

Enter a comment in the box below; it will be added as a comment to all affected tickets