/** * Goes through a list of built-up changes and commits them to the * backend. * * This will send email updates by default, update the ticket log, etc. * * @see change() * * @param string $user The Horde user of the changes to be made. * Defaults to the current user. * @param integer $transaction The transaction these changes are part of. * Defaults to a new transaction. * @param boolean $notify Send ticket notifications? */ public function commit($user = null, $transaction = null, $notify = true) { global $conf, $whups_driver; if (!count($this->_changes)) { return; } if (is_null($user)) { $user = $GLOBALS['registry']->getAuth(); } $author_email = isset($this->_changes['comment-email']['to']) ? $this->_changes['comment-email']['to'] : null; if (is_null($transaction)) { // Get a new transaction id from the backend. $transaction = $whups_driver->newTransaction($user, $author_email); } // If this is a guest update, the comment id is going to map to the // requester pseudo-username. if ($user === false) { $user = '******' . $transaction . '_transaction'; } // Run hook before setting the dates. try { $this->_changes = Horde::callHook('ticket_update', array($this, $this->_changes), 'whups'); } catch (Horde_Exception_HookNotSet $e) { } // Update cached dates. $timestamp = time(); $this->_changes['date_updated'] = array('to' => $timestamp); if (isset($this->_changes['state'])) { $state = $whups_driver->getState($this->_changes['state']['to']); if ($state['category'] == 'assigned') { $this->_changes['date_assigned'] = array('to' => $timestamp); $this->_changes['date_resolved'] = array('to' => null); } elseif ($state['category'] == 'resolved') { $this->_changes['date_resolved'] = array('to' => $timestamp); } else { $this->_changes['date_resolved'] = array('to' => null); } } $updates = array(); foreach ($this->_changes as $detail => $values) { $value = $values['to']; switch ($detail) { case 'owners': // Fetch $oldOwners list; then loop through $value adding and // deleting as needed. if ($owners = $whups_driver->getOwners($this->_id)) { $oldOwners = reset($owners); } else { $oldOwners = array(); } $this->_changes['oldowners'] = $oldOwners; foreach ($value as $owner) { if (!$oldOwners || array_search($owner, $oldOwners) === false) { $whups_driver->addTicketOwner($this->_id, $owner); $whups_driver->updateLog($this->_id, $user, array('assign' => $owner), $transaction); } else { // Remove $owner from the old owners list; anyone left // in $oldOwners will be removed. unset($oldOwners[array_search($owner, $oldOwners)]); } } // Delete removed owners and log the removals. if (is_array($oldOwners)) { foreach ($oldOwners as $owner) { $whups_driver->deleteTicketOwner($this->_id, $owner); $whups_driver->updateLog($this->_id, $user, array('unassign' => $owner), $transaction); } } break; case 'comment': $commentId = $whups_driver->addComment($this->_id, $value, $user, $author_email); // Store the comment id in the updates array for the log. $updates['comment'] = $commentId; if (!empty($this->_changes['comment-perms'])) { $this->addCommentPerms($commentId, $this->_changes['comment-perms']['to']); } break; case 'comment-email': case 'comment-perms': // Skip these, handled in the comment case. break; case 'message': if (isset($conf['vfs']['type'])) { $updates['message'] = $this->addMessage($value); } break; case 'delete-message': if (isset($conf['vfs']['type'])) { $this->deleteMessage($value); // Store the deleted message id in the updates array for the // log. $updates['delete-message'] = $value; } break; case 'attachment': $this->addAttachment($value['name'], $value['tmp_name']); // Store the new file name in the updates array for the // log. $updates['attachment'][] = $value['name']; break; case 'attachments': foreach ($value as $attachment) { $this->addAttachment($attachment['name'], $attachment['tmp_name']); // Store the new file name in the updates array for the // log. $updates['attachment'][] = $attachment['name']; } break; case 'delete-attachment': $this->deleteAttachment($value); // Store the deleted file name in the updates array for // the log. $updates['delete-attachment'] = $value; break; case 'queue': // Reset version if new queue is not versioned. $newqueue = $whups_driver->getQueue($value); if (empty($newqueue['queue_versioned'])) { $updates['version'] = 0; } $updates['queue'] = $value; break; default: if (strpos($detail, 'attribute_') === 0 && !is_string($value)) { $value = Horde_Serialize::Serialize($value, Horde_Serialize::JSON); } $updates[$detail] = $value; break; } } if (count($updates)) { $whups_driver->updateTicket($this->_id, $updates); $whups_driver->updateLog($this->_id, $user, $updates, $transaction); } // Reload $this->_details to make sure we have the latest information. // // @todo Only touch the db if we have to. $details = $whups_driver->getTicketDetails($this->_id); $this->_details = array_merge($this->_details, $details); // Send notification emails to all ticket listeners. if ($notify) { $this->notify($user, false); } // Reset the changes array. $this->_changes = array(); }