* @license PHP License * @package WB * @subpackage content */ /** * Load classes */ WBClass::load('WBITS' , 'WBUser'); /** * Wombat Incident Ticket System: Ticket * * @version 1.3.0 * @package WB * @subpackage content */ class WBITS_Ticket extends WBStdClass { /** * Ticket Data * @var array */ private $data = array(); /** * Ticket Id * @var string */ private $id = ''; /** * Ticket obscure string * @var string */ private $obscure = ''; /** * Table access * @var WBDatasource_Table_ITS */ private $table; /** * relation table * @var WBDatasource_RelationTable */ private $relTable = null; /** * ITS configuration * Loaded using WBITS::getConfig * @var array */ private $config = array(); /** * Constructor * * @param array $parameter */ public function __construct($parameter = array()) { // load general config $this->config = WBITS::getConfig(); // load relation config $config = WBClass::create('WBConfig'); if ($config->load('its/relation')) { $this->setRelationConfig($config->get('relation', array())); } if (isset($parameter['table']) && $parameter['table']) { $this->table = $parameter['table']; return; } $this->table = WBClass::create('WBDatasource_Table_ITS'); $this->table->switchTranslation(false); } /** * Configure Relation Table * * Use relation configuration to set up related tables * * @see WBDatasource_RelationTable * @param array $config */ private function setRelationConfig($conf = array()) { if (empty($conf)) { $this->relTable = null; return; } if (!$this->relTable) { $this->relTable = WBClass::create('WBDatasource_RelationTable'); $this->relTable->setTable($this->table); } $this->relTable->setConfig(WBITS::TABLE_TICKET, $conf); } /** * Load ticket by obscureId * * @see loadById() * @param string $obscureId * @return WBITS_Ticket */ public function loadByObscureId($obscureId) { $obscureId = strtoupper($obscureId); // extract id and load by id $pattern = '/^([A-Z0-9]*[A-Z])(\d+)$/'; if (!preg_match($pattern, $obscureId, $match)) { $this->flush(); return $this; } $this->loadById($match[2]); if (empty($this->id)) { return $this; } // ignore cases for check if ($this->obscure != $obscureId) { $this->flush(); return $this; } return $this; } /** * Load ticket by id * * Only for internal use - otherwise protection with obscure id will be lost. * * @param string $id * @return WBITS_Ticket */ public function loadById($id) { $this->flush(); $options = array( 'limit' => 2, 'callback' => WBClass::create('WBITS_DatasourceCallback') ); $list = $this->table->get(WBITS::TABLE_TICKET, $id, null, array(), $options); if (1 != count($list)) { return $this; } $this->id = $id; $this->obscure = $list[0]['obscureid']; // add related data if ($this->relTable) { $this->relTable->inject($list[0]);; } unset($list[0]['id']); unset($list[0][$this->table->getIdentifier(WBITS::TABLE_TICKET)]); $this->data = $list[0]; return $this; } /** * Get Ticket Id */ public function getId() { return $this->id; } /** * Get Ticket Obscure Id */ public function getObscureId() { return $this->obscure; } /** * Get ticket data */ public function getData() { return $this->data; } /** * Save ticket Data in table * * @param array $data */ public function save($data) { $event = 'its:ticket:new:'; $msg = 'Created ticket'; $eData = array(); $diff = array(); // add current user's id $uPrimary = $this->table->getIdentifier('user'); $data[$uPrimary] = WBUser::getCurrent()->getId(); if (empty($data[$uPrimary])) { $data[$uPrimary] = 0; } // extract comment $comment = ''; if (isset($data['comment'])) { $comment = trim($data['comment']); unset($data['comment']); } // strip
at the end of a paragraph if (isset($data['blurb'])) { $data['blurb'] = trim($data['blurb']); if (!empty($data['blurb'])) { $data['blurb'] = str_replace('

', '

', $data['blurb']); // force

-tags $data['blurb'] = trim($data['blurb']); if (0 != strncmp('

', $data['blurb'], 3)) { $data['blurb'] = '

' . $data['blurb'] . '

'; } } } if (empty($this->id)) { $id = '__new'; // default values if (!isset($data['namespace']) || empty($data['namespace'])) { $ns = $this->config['namespace']; $data['namespace'] = $ns; } else { $ns = $data['namespace']; } $event .= $ns; if (!isset($data['assigneduid']) || empty($data['assigneduid'])) { $data['assigneduid'] = 0; } if (empty($data['status'])) { $data['status'] = 'new'; } $data['statuschanged'] = gmdate('Y-m-d H:i:s'); WBClass::load('WBDatasource_ObscureCode'); $data['obscure'] = strtoupper(WBDatasource_ObscureCode::mkRandObscure($this->config['obscurelength'], true, true)); $this->obscure = $data['obscure']; } else { $id = $this->id; $ns = $this->data['namespace']; // ignore these keys because they refer to auto generated data $ignore = array( 'created', 'changed', 'statuschanged', 'obscureid', 'deleted', 'obscure', $uPrimary ); // check what was changed foreach ($this->data as $k => $v) { if (in_array($k, $ignore)) { continue; } if (!isset($data[$k])) { continue; } if ($data[$k] == $v) { continue; } if (is_array($v)) { $diff[$k] = array(); foreach ($v as $tmp) { if (!in_array($tmp, $data[$k])) { $diff[$k][] = array( 'value' => $tmp, 'action' => 'deleted' ); } } foreach ($data[$k] as $tmp) { if (!in_array($tmp, $v)) { $diff[$k][] = array( 'value' => $tmp, 'action' => 'added' ); } } continue; } $diff[$k] = $v; } // don't save ticket if (empty($diff)) { // trigger comment if (!empty($comment)) { $event = 'its:ticket:commented:' . $ns; $msg = 'Ticket commented'; $eData = array_merge($eData, $this->data); $eData['id'] = $this->id; $eData['obscureid'] = $this->obscure; $eData['comment'] = $comment; WBEvent::trigger($event, $msg, $eData); } return; } $eData['diffkeys'] = implode(', ', array_keys($diff)); $eData['comment'] = $comment; $data = array_intersect_key($data, $this->data); $msg = 'Ticket data changed ({DIFFKEYS})'; // change of namespace - happens only rarely if (isset($data['namespace'])) { $ns = $data['namespace']; } // event name $event = 'its:ticket:saved:' . $ns; // status changes if (isset($data['status']) && $data['status'] != $this->data['status']) { $event = 'its:ticket:statuschanged:' . $data['status'] . ':' . $ns; $msg = 'Ticket status changed from {STATUSOLD} to {STATUS}'; $eData['statusold'] = $this->data['status']; $data['statuschanged'] = gmdate('Y-m-d H:i:s'); } // assignee changes else if (isset($data['assigneduid']) && $data['assigneduid'] != $this->data['assigneduid']) { $event = 'its:ticket:reassigned:' . $ns; $msg = 'Removed assignment from {ASSIGNEDUIDOLD}, Set assignment to {ASSIGNEDUID}.'; } // add assigneduidold anyway if (isset($data['assigneduid']) && $data['assigneduid'] != $this->data['assigneduid']) { $eData['assigneduidold']= $this->data['assigneduid']; } } if ($this->relTable) { $this->relTable->extract($data); if ('__new' != $id) { $this->relTable->delete($this->id, true); } } $this->id = $this->table->save(WBITS::TABLE_TICKET, $id, $data); if ('__new' == $id) { $this->obscure .= $this->id; } $this->data = array_merge($this->data, $data); if ($this->relTable) { $this->relTable->add($this->id); // clean up current data $this->data[$this->table->getIdentifier(WBITS::TABLE_TICKET)] = $this->id; $this->relTable->inject($this->data); unset($this->data[$this->table->getIdentifier(WBITS::TABLE_TICKET)]); } $eData = array_merge($eData, $this->data); $eData['id'] = $this->id; $eData['obscureid'] = $this->obscure; $eData['diff'] = $diff; WBEvent::trigger($event, $msg, $eData); } /** * Flush ticket data */ private function flush() { $this->data = array(); $this->obscure = ''; $this->id = ''; } }