diff --git a/include/class.export.php b/include/class.export.php index 521eb7cefbdb89605ebe87e04ea2d644f359d60c..6f8ec713f3437a2cb21a264a80aa4637966ddd7e 100644 --- a/include/class.export.php +++ b/include/class.export.php @@ -42,48 +42,40 @@ class Export { # attachments associated with each, ... static function dumpTickets($sql, $how='csv') { // Add custom fields to the $sql statement - $cdata = $fields = $select = array(); + $cdata = $fields = array(); foreach (TicketForm::getInstance()->getFields() as $f) { // Ignore core fields - if (in_array($f->get('name'), array('subject','priority'))) + if (in_array($f->get('name'), array('priority'))) continue; // Ignore non-data fields elseif (!$f->hasData() || $f->isPresentationOnly()) continue; - $name = $f->get('name') ? $f->get('name') : 'field_'.$f->get('id'); - $key = '__field_'.$f->get('id'); - // Fetch ID values for ID-based data - if ($f->hasIdValue()) { - $name .= '_id'; - } - $cdata[$key] = $f->get('label'); + $name = $f->get('name') ?: 'field_'.$f->get('id'); + $key = 'cdata.'.$name; $fields[$key] = $f; - $select[] = "cdata.`$name` AS __field_".$f->get('id'); + $cdata[$key] = $f->getLocal('label'); } - if ($select) - $sql = str_replace(' FROM ', ',' . implode(',', $select) . ' FROM ', $sql); return self::dumpQuery($sql, array( 'number' => __('Ticket Number'), - 'ticket_created' => __('Date'), - 'subject' => __('Subject'), - 'name' => __('From'), - 'email' => __('From Email'), - 'priority_desc' => __('Priority'), - 'dept_name' => __('Department'), - 'helptopic' => __('Help Topic'), + 'created' => __('Date'), + 'cdata.subject' => __('Subject'), + 'user.name' => __('From'), + 'user.default_email.address' => __('From Email'), + 'cdata.:priority.priority_desc' => __('Priority'), + 'dept::getLocalName' => __('Department'), + 'topic::getName' => __('Help Topic'), 'source' => __('Source'), - 'status' => __('Current Status'), - 'effective_date' => __('Last Updated'), + 'status::getName' =>__('Current Status'), + '::getEffectiveDate' => __('Last Updated'), 'duedate' => __('Due Date'), 'isoverdue' => __('Overdue'), 'isanswered' => __('Answered'), - 'assigned' => __('Assigned To'), - 'staff' => __('Agent Assigned'), - 'team' => __('Team Assigned'), - 'thread_count' => __('Thread Count'), - 'attachments' => __('Attachment Count'), + 'staff::getName' => __('Agent Assigned'), + 'team::getName' => __('Team Assigned'), + #'thread_count' => __('Thread Count'), + #'attachments' => __('Attachment Count'), ) + $cdata, $how, array('modify' => function(&$record, $keys) use ($fields) { @@ -213,32 +205,22 @@ class Export { class ResultSetExporter { var $output; - function ResultSetExporter($sql, $headers, $options=array()) { + function __construct($sql, $headers, $options=array()) { $this->headers = array_values($headers); - if ($s = strpos(strtoupper($sql), ' LIMIT ')) - $sql = substr($sql, 0, $s); + // Remove limit and offset + $sql->limit(null)->offset(null); # TODO: If $filter, add different LIMIT clause to query $this->options = $options; $this->output = $options['output'] ?: fopen('php://output', 'w'); - $this->_res = db_query($sql, true, true); - if ($row = db_fetch_array($this->_res)) { - $query_fields = array_keys($row); - $this->headers = array(); - $this->keys = array(); - $this->lookups = array(); - foreach ($headers as $field=>$name) { - if (array_key_exists($field, $row)) { - $this->headers[] = $name; - $this->keys[] = $field; - # Remember the location of this header in the query results - # (column-wise) so we don't have to do hashtable lookups for every - # column of every row. - $this->lookups[] = array_search($field, $query_fields); - } - } - db_data_reset($this->_res); + $this->headers = array(); + $this->keys = array(); + foreach ($headers as $field=>$name) { + $this->headers[] = $name; + $this->keys[] = $field; } + $this->_res = $sql->getIterator(); + $this->_res->rewind(); } function getHeaders() { @@ -246,12 +228,30 @@ class ResultSetExporter { } function next() { - if (!($row = db_fetch_row($this->_res))) + if (!$this->_res->valid()) return false; + $object = $this->_res->current(); + $this->_res->next(); + $record = array(); - foreach ($this->lookups as $idx) - $record[] = $row[$idx]; + + foreach ($this->keys as $field) { + list($field, $func) = explode('::', $field); + $path = explode('.', $field); + $current = $object; + // Evaluate dotted ORM path + if ($field) { + foreach ($path as $P) { + $current = $current->{$P}; + } + } + // Evalutate :: function call on target current + if ($func && method_exists($current, $func)) { + $current = $current->{$func}(); + } + $record[] = (string) $current; + } if (isset($this->options['modify']) && is_callable($this->options['modify'])) $record = $this->options['modify']($record, $this->keys); diff --git a/include/class.staff.php b/include/class.staff.php index 231717bef71bf8aa720b5f67c7f22a19fadc1f5b..6fcaf873fb1b299610fbf06faa4a7ac817922b2e 100644 --- a/include/class.staff.php +++ b/include/class.staff.php @@ -32,6 +32,10 @@ class StaffModel extends VerySimpleModel { ), ), ); + + function getName() { + return $this->firstname . ' ' . $this->lastname; + } } class Staff extends AuthenticatedUser { diff --git a/include/class.ticket.php b/include/class.ticket.php index 81201705984c97f9c26b0a00cfa30d1f46762045..4ca2477a3b8d39652ca5ec086f9180aea85f2935 100644 --- a/include/class.ticket.php +++ b/include/class.ticket.php @@ -77,12 +77,12 @@ class TicketModel extends VerySimpleModel { } function getEffectiveDate() { - return max( + return Format::datetime(max( strtotime($this->lastmessage), strtotime($this->closed), strtotime($this->reopened), strtotime($this->created) - ); + )); } function delete() { diff --git a/include/staff/tickets.inc.php b/include/staff/tickets.inc.php index b0dca99dd0d197f0a1d7fb235f381e8936eabe0d..cb0c1011c644a881a8f187bfd8887b1f6b20a8b4 100644 --- a/include/staff/tickets.inc.php +++ b/include/staff/tickets.inc.php @@ -237,7 +237,7 @@ $_SESSION[':Q:tickets'] = $tickets; <td title="<?php echo $T->user->getDefaultEmailAddress(); ?>" nowrap> <a class="Icon <?php echo strtolower($T->source); ?>Ticket ticketPreview" title="Preview Ticket" href="tickets.php?id=<?php echo $T->ticket_id; ?>"><?php echo $tid; ?></a></td> - <td align="center" nowrap><?php echo Format::datetime($T->getEffectiveDate()); ?></td> + <td align="center" nowrap><?php echo $T->getEffectiveDate(); ?></td> <td><a <?php if ($flag) { ?> class="Icon <?php echo $flag; ?>Ticket" title="<?php echo ucfirst($flag); ?> Ticket" <?php } ?> href="tickets.php?id=<?php echo $T->ticket_id; ?>"><?php echo $subject; ?></a> <?php @@ -292,8 +292,8 @@ $_SESSION[':Q:tickets'] = $tickets; <?php if($total>0){ //if we actually had any tickets returned. echo '<div> '.__('Page').':'.$pageNav->getPageLinks().' '; - echo '<a class="export-csv no-pjax" href="?a=export&h=' - .$hash.'&status='.$_REQUEST['status'] .'">'.__('Export').'</a> <i class="help-tip icon-question-sign" href="#export"></i></div>'; + echo '<a class="export-csv no-pjax" href="?a=export&status=' + .$_REQUEST['status'] .'">'.__('Export').'</a> <i class="help-tip icon-question-sign" href="#export"></i></div>'; } ?> </form> </div> diff --git a/scp/tickets.php b/scp/tickets.php index 74fa99bff5df98e7fcc711d74bd8f398e0564872..4a84530660188770bbf136d41b6132994ab47482 100644 --- a/scp/tickets.php +++ b/scp/tickets.php @@ -465,9 +465,7 @@ if($ticket) { $inc = 'ticket-open.inc.php'; elseif($_REQUEST['a'] == 'export') { $ts = strftime('%Y%m%d'); - if (!($token=$_REQUEST['h'])) - $errors['err'] = __('Query token required'); - elseif (!($query=$_SESSION['search_'.$token])) + if (!($query=$_SESSION[':Q:tickets'])) $errors['err'] = __('Query token not found'); elseif (!Export::saveTickets($query, "tickets-$ts.csv", 'csv')) $errors['err'] = __('Internal error: Unable to dump query results');