Hello,

I have posted a few times about a MOD which has been put together. Ticket Linking & Ticket Categorization. The way that the MOD was implemented it was too time consuming for me to share it with the community and separate them. So here they are together.

There is a bunch of additional PHP files which you will need to add into several folders as well as make several changes to the back-end database.

Please make these changes in a test environment first before implementing them in your live environment.

Without further delay....

The Mod:

1. Edit include\class.ticket.php

A)

Search for the following code:

var $overdue;

Below it Add:

var $category_Id;

B)

Search for the following code:

function Ticket($id,$exid=false){

$this->load($id);

}

Replace it with:

function Ticket($id,$exid=false){

$this->load($id);

// $this->getParentTickets();

// $this->getChildTickets();

}

C)

Search for the Following code:

function load($id) {

$sql =' SELECT ticket.*,topic.topic_id as topicId,lock_id,dept_name,priority_desc FROM '.TICKET_TABLE.' ticket '.

Replace it with:

function getParentTickets($lticketId)

{

$sql= "SELECT links.id as LinkId,child_ticket_id,parent_ticket_id,subject,status,ticket_id FROM ".LINK_TABLE." links

INNER JOIN ".TICKET_TABLE. " tickets ON links.parent_ticket_id=tickets.ticketId

WHERE child_ticket_id=".$lticketId;

$res=db_query($sql);

$result=array();

if($res && db_num_rows($res))

{

list($LinkId,$child_ticket_id,$parent_ticket_id,$subject,$status,$ticket_id)= db_fetch_row($res);

$result=$LinkId;

$result=$child_ticket_id;

$result=$parent_ticket_id;

$result=$subject;

$result=$status;

$result=$ticket_id;

}

return $result;

}

function getChildTickets($lticketId){

$sql= "SELECT links.id as LinkId,child_ticket_id,parent_ticket_id,subject,status,ticket_id FROM ".LINK_TABLE." links

INNER JOIN ".TICKET_TABLE. " tickets ON links.child_ticket_id=tickets.ticketId

WHERE parent_ticket_id=".$lticketId;

$res=db_query($sql);

$result=array();

if($res && db_num_rows($res))

{

$i=0;

while($row= db_fetch_row($res)){

$result=$row;

$result=$row;

$result=$row;

$result=$row;

$result=$row;

$result=$row;

$i++;

}

}

return $result;

}

function insertlinkTicket($var,&$errors) {

global $cfg,$thisuser;

$params = new Validator($fields);

if(!$params->validate($var)){

$errors=array_merge($errors,$params->errors());

}

$child_ticket_id=$var;

$parent_ticket_id=$var;

$sql="INSERT INTO ost_ticket_link(child_ticket_id,parent_ticket_id) values($child_ticket_id,$parent_ticket_id)";

if(db_query($sql)){

$this->getParentTickets($parent_ticket_id);

$this->getChildTickets($parent_ticket_id);

return true;

}

return false;

}

function updatecatid($var,&$errors) {

global $cfg,$thisuser;

$fields=array();

$fields = array('type'=>'int', 'required'=>1, 'error'=>'Ticket type required');

$fields = array('type'=>'int', 'required'=>1, 'error'=>'Main category required');

$fields = array('type'=>'int', 'required'=>1, 'error'=>'Sub category required');

$params = new Validator($fields);

if(!$params->validate($var)){

$errors=array_merge($errors,$params->errors());

}

$sql='UPDATE '.TICKET_TABLE.' SET category_Id='.db_input($var).',updated=NOW() WHERE ticket_id='.db_input($this->getId());

if(db_query($sql)){

$this->reload();

return true;

}

return false;

}

function load($id) {

$sql =' SELECT ticket.*,topic.topic_id as topicId,lock_id,dept_name,priority_desc,category_Id FROM '.TICKET_TABLE.' ticket '.

D)

Find the following code:

$this->overdue =$row;

Below Add the following code:

$this->category_Id=$row;

E)

Find the following code:

function isLocked() {

return $this->lock_id?true;

}

//GET

Below Add the following code:

function getCategory_Id(){

return $this->category_Id;

}

F)

Find the following code:

db_query('DELETE FROM '.TICKET_NOTE_TABLE.' WHERE ticket_id='.db_input($this->getId()));

Below Add the following code:

db_query('DELETE FROM '.LINK_TABLE.' WHERE child_ticket_id='.db_input($this->getExtId()));

G)

Search for the following code:

$fields = array('type'=>'int', 'required'=>0, 'error'=>'Invalid Selection');

ABOVE add the following code:

$fields = array('type'=>'text', 'required'=>1, 'error'=>'Categorization required');

H)

Search for the following code:

if(!$errors){

$sql='UPDATE '.TICKET_TABLE.' SET updated=NOW() '.

',email='.db_input($var).

Add the following code below:

',category_Id='.db_input( $var).

I)

Search for the following code:

if(strcasecmp($origin,'web')==0) { //Help topic only applicable on web tickets.

Above Add the following code:

$fields = array('type'=>'text', 'required'=>1, 'error'=>'Categorization required');

J)

Search for the following code:

//We are ready son...hold on to the rails.

$extId=Ticket:();

$sql= 'INSERT INTO '.TICKET_TABLE.' SET created=NOW() '.

',ticketID='.db_input($extId).

Below Add the following code:

',category_Id='.db_input( $var).

2. Edit scp\tickets.php

A)

Search for the following code:

if(!$errors && ($id=$_REQUEST?$_REQUEST:$_POST) && is_numeric($id)) {

$deptID=0;

$ticket= new Ticket($id);

replace with:

if(!$errors && ($id=$_REQUEST?$_REQUEST:$_POST) && is_numeric($id)) {

$deptID=0;

$ticket= new Ticket($id);

$parentArray= $ticket->getParentTickets($ticket->getExtId());

$childArray = $ticket->getChildTickets($ticket->getExtId());

B)

Search for the following Code:

}elseif($_REQUEST=='open') {

//TODO: Check perm here..

$page='newticket.inc.php';

}

Below Add the following:

if(isset($_GET) && !empty($_GET))

{

$deletequery="DELETE FROM ".LINK_TABLE." WHERE id=".$_GET;

db_query($deletequery);

$msg3='Ticket Linkage deleted successfully';

}

****NOTE***** Another Post with attached files, Screencaps and the rest of the MOD will Follow

Continued....

C)

Search for the following code:

if($ticket && $ticket->getId()) {

//More tea please.

$errors=array();

$lock=$ticket->getLock(); //Ticket lock if any

$statusKeys=array('open'=>'Open','Reopen'=>'Open','Close'=>'Closed');

switch(strtolower($_POST)):

Below Add the following:

case 'categorization':

if(!empty($_POST)){

$_POST=$rep;

$_POST=$rep;

$_POST=$_POST;

}

if(empty($_POST))

{

$errors1='Invalid inputs . Please fill the complete form';

}

else if($ticket->updatecatid($_POST,$errors1)){

$msg1='Ticket updated successfully';

$page='viewticket.inc.php';

}elseif(!$errors1) {

$errors='Error(s) occured! Try again.';

}

break;

case 'linktoticket':

//check if new ticket is child of someone, if yes then do not allow to add

$linkTicketid= trim($_POST);

$currentTicketid= $ticket->getExtId();

if(!empty($linkTicketid))

{

if($currentTicketid==$linkTicketid){

$errors='You cannot link to own Ticket.Please add different Ticket Number ';

}

else

{

$sql= "SELECT id as LinkId FROM ".LINK_TABLE." WHERE child_ticket_id=".$_POST ;//." OR parent_ticket_id=".$_POST;

$res=db_query($sql);

if($res && db_num_rows($res))

list($LinkId)=db_fetch_row($res);

if(empty($LinkId)){

//add value in database

//check whether ticket is exists in ticket database or not

$sql= "SELECT ticketID FROM ".TICKET_TABLE." WHERE ticketID=".$_POST;

$res=db_query($sql);

list($isTicketExist)=db_fetch_row($res);

if(empty($isTicketExist)){

$errors='Please enter valid Ticket Linkage ';

}

else

{

$sql= "SELECT id as LinkId FROM ".LINK_TABLE." WHERE parent_ticket_id=".$currentTicketid;//." OR parent_ticket_id=".$_POST;

$res=db_query($sql);

if($res && db_num_rows($res))

list($LinkId)=db_fetch_row($res);

if(empty($LinkId)){

$ticket->insertlinkTicket($_POST,$errors2);

$msg2='Ticket Link created successfully';

}

else

$errors='This ticket already parent ';

$page='viewticket.inc.php';

}

}

else{

$errors='This ticket already child';

}

}//else if($currentTicketid==$linkTicketid)

}

else{

$errors='Please enter ticket # to link';

}

break;

D)

Search for the following Code:

if($ticket->close()){

$msg='Ticket #'.$ticket->getExtId().' status set to CLOSED';

$note='Ticket closed without response by '.$thisuser->getName();

$ticket->logActivity('Ticket Closed',$note);

$page=$ticket=null; //Going back to main listing.

}else{

$errors='Problems closing the ticket. Try again';

}

Replace with:

$qry = "SELECT category_Id FROM ".TICKET_TABLE." ticket WHERE ticket_id = '".$_REQUEST."'";

$qryres=db_fetch_array(db_query($qry));

$catnotfound = $qryres;

if(empty($catnotfound))

{

$errors='Please apply categorization before closing ticket';

}

else

{

if($ticket->close()){

$msg='Ticket #'.$ticket->getExtId().' status set to CLOSED';

$note='Ticket closed without response by '.$thisuser->getName();

$ticket->logActivity('Ticket Closed',$note);

$page=$ticket=null; //Going back to main listing.

}else{

$errors='Problems closing the ticket. Try again';

}

}

E)

Search for the following:

',count(overdue.ticket_id) as overdue, count(assigned.ticket_id) as assigned '.

' FROM '.TICKET_TABLE.' ticket '.

'LEFT JOIN '.TICKET_TABLE.' open ON open.ticket_id=ticket.ticket_id AND open.status=\'open\' AND open.isanswered=0 '.

'LEFT JOIN '.TICKET_TABLE.' answered ON answered.ticket_id=ticket.ticket_id AND answered.status=\'open\' AND answered.isanswered=1 '.

'LEFT JOIN '.TICKET_TABLE.' overdue ON overdue.ticket_id=ticket.ticket_id AND overdue.status=\'open\' AND overdue.isoverdue=1 '.

'LEFT JOIN '.TICKET_TABLE.' assigned ON assigned.ticket_id=ticket.ticket_id AND assigned.staff_id='.db_input($thisuser->getId());

Replace with the following code:

',count(overdue.ticket_id) as overdue, count(assigned.ticket_id) as assigned '.

' FROM '.TICKET_TABLE.' ticket '.

'LEFT JOIN '.TICKET_TABLE.' open ON open.ticket_id=ticket.ticket_id AND open.status=\'open\' AND open.isanswered=0 '.

'LEFT JOIN '.TICKET_TABLE.' answered ON answered.ticket_id=ticket.ticket_id AND answered.status=\'open\' AND answered.isanswered=1 '.

'LEFT JOIN '.TICKET_TABLE.' overdue ON overdue.ticket_id=ticket.ticket_id AND overdue.status=\'open\' AND overdue.isoverdue=1 '.

'LEFT JOIN '.TICKET_TABLE.' assigned ON assigned.ticket_id=ticket.ticket_id AND assigned.staff_id='.db_input($thisuser->getId()).

' LEFT JOIN '.LINK_TABLE.' link ON ticket.ticketID=link.child_ticket_id';

F)

Search for the following If Statement:

if(!$thisuser->isAdmin()){

Replace the entire IF Statement (it ends with the same else staement as the replacement code below) with the following code:

if(!$thisuser->isAdmin()){

$sql.=' WHERE ticket.dept_id IN('.implode(',',$thisuser->getDepts()).') OR ticket.staff_id='.db_input($thisuser->getId());

}

else

$sql.= ' WHERE ISNULL(link.child_ticket_id)';

Continued...again

3. Edit /include/staff/viewticket.inc.php

A)

Search for the following code:

$warn.='&nbsp;&nbsp;<span class="Icon overdueTicket">Marked overdue!</span>';

Below it add:

/************************************ NEW BLOCK ADDED ***********************************/

$ticketID=$ticket->getExtId();

$sql="SELECT category_Id FROM ".TICKET_TABLE." WHERE ticket_id=".$id;

$recordsetcatid=db_fetch_array(db_query($sql));

$parentArray=$ticket->getParentTickets($ticketID);

$childArray=$ticket->getChildTickets($ticketID);

$cat_id=$recordsetcatid;

require_once(INCLUDE_DIR.'class.category.php');

$category= new Category($cat_id);

$rep=$category->getInfo();

$sql="SELECT ticket_typeid, ticket_type FROM ".TICKET_TYPE_TABLE." WHERE status=1";

$tickettypeObj= db_query($sql);

$sql="SELECT cat_id,main_category FROM ".TICKET_CATEGORY_TABLE." WHERE status=1 AND type_entry='Main Category' AND ticket_type=".$rep;

$maincatObj= db_query($sql);

$sql="SELECT cat_id,sub_category FROM ".TICKET_CATEGORY_TABLE." WHERE status=1 AND type_entry='Sub Category' AND main_category=".$rep;

$subcatObj= db_query($sql);

$sql="SELECT cat_id,category_detail FROM ".TICKET_CATEGORY_TABLE." WHERE status=1 AND type_entry='Category Details' AND sub_category=".$rep;

$catdetailObj= db_query($sql);

/************************************ NEW BLOCK ADDED END***********************************/

B)

The following should be on the line directly below the code just added ‘?>’ directly below this add the following block of code: (around line 55)

<head>

<script src="jquery-1.7.1.min.js" type="text/javascript"></script>

<script>

function getXMLHTTP() { //fuction to return the xml http object

var xmlhttp=false;

try{

xmlhttp=new XMLHttpRequest();

}

catch(e) {

try{

xmlhttp= new ActiveXObject("Microsoft.XMLHTTP");

}

catch(e){

try{

xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");

}

catch(e1){

xmlhttp=false;

}

}

}

return xmlhttp;

}

function getMaincategory(strURL) {

var req = getXMLHTTP();

if (req) {

req.onreadystatechange = function() {

if (req.readyState == 4) {

if (req.status == 200) {

document.getElementById('maincategorydiv').innerHTML=req.responseText;

document.getElementById('subcategorydiv').innerHTML='<select><option value="">Select Sub-Category</option></select>&nbsp;<font class="error">*&nbsp;</font> ';

document.getElementById('categorydetailsdiv').innerHTML='<select><option value="">Select Category Detail</option></select>&nbsp;<font class="error">*&nbsp;</font> ';

} else {

alert("There was a problem while using XMLHTTP:\n" + req.statusText);

}

}

}

req.open("GET", strURL, true);

req.send(null);

}

}

function getSubcategory(ticket,maincategory) {

if(ticket=="" && ticket==null) {

var sel = document.getElementById('ticketid');

var ticket= sel.options.value;

}

var strURL="ajax.php?api=autoaddsubticket&f=getsubcategory&ticket="+ticket+"&maincategory="+maincategory;

var req = getXMLHTTP();

if (req) {

req.onreadystatechange = function() {

if (req.readyState == 4) {

if (req.status == 200) {

document.getElementById('hiddenfield').value= document.getElementById('main_category').value;

document.getElementById('subcategorydiv').innerHTML=req.responseText;

document.getElementById('categorydetailsdiv').innerHTML='<select><option value="">Select Category Detail</option></select>&nbsp;<font class="error">*&nbsp;</font> ';

} else {

alert("There was a problem while using XMLHTTP:\n" + req.statusText);

}

}

}

req.open("GET", strURL, true);

req.send(null);

}

}

function getcategorydetails(ticket,maincategory,subcategory) {

if(ticket=="" && ticket==null) {

var sel = document.getElementById('ticketid');

var ticket= sel.options.value;

}

if(maincategory=="" && maincategory==null) {

var sell = document.getElementById('ticketid');

var maincategory= sel.options.value;

}

var strURL="ajax.php?api=autoaddsubticket&f=getcategorydetails&ticket="+ticket+"&maincategory="+maincategory+"&subcategory="+subcategory;

var req = getXMLHTTP();

if (req) {

req.onreadystatechange = function() {

if (req.readyState == 4) {

if (req.status == 200) {

document.getElementById('hiddenfieldsub').value=document.getElementById('sub_category').value;

document.getElementById('categorydetailsdiv').innerHTML=req.responseText;

} else {

alert("There was a problem while using XMLHTTP:\n" + req.statusText);

}

}

}

req.open("GET", strURL, true);

req.send(null);

}

}

function getvalue(){

document.getElementById('hiddenfieldcat_id').value=document.getElementById('category').value;

}

</script>

</head>

C)

Find the following block of code:

</tr></td>

</table>

<?}?>

<br>

Replace it with:

<?}?>

</td>

<?php include('viewticketpart.inc.php');?>

4. Edit /scp/admin.php

A)

Search for the following code:

require_once(INCLUDE_DIR.'class.mailfetch.php');

Below it Add:

if($_GET=='mass_process'){ $_POST='mass_process';}

Continued....

B)

Search for the following block of code:

//WELCOME TO THE HOUSE OF PAIN.

$errors=array(); //do it anyways.

switch(strtolower($_REQUEST)):

Below it add:

case 'cats':

require_once(INCLUDE_DIR.'class.category.php');

if($_POST){

$do=strtolower($_POST);}

else{ $do=strtolower($_REQUEST); }

switch($do){

case 'search':

if($_POST=='Search'){

$msg='';

}

break;

case 'addtickettype':

if(($gID=Category:($_POST,$errors))){

$msg='Ticket Type '.Format:($_POST).' created successfully';

}elseif(!$errors) {

$errors='Error(s) occured. Try again.';

}

break;

case 'addmaincat':

if(($gID=Category:($_POST,$errors))){

$msg='Main Category '.Format:($_POST).' created successfully';

}elseif(!$errors) {

$errors='Error(s) occured. Try again.';

}

break;

case 'addsubcat':

if(($gID=Category:($_POST,$errors))){

$msg='Sub Category '.Format:($_POST).' created successfully';

}elseif(!$errors) {

$errors='Error(s) occured. Try again.';

}

break;

case 'catdtls':

if(($gID=Category:($_POST,$errors))){

$msg='Add Category details '.Format:($_POST).' created successfully';

}elseif(!$errors) {

$errors='Error(s) occured. Try again.';

}

break;

case 'updateticket':

if(($gID=Category:($_POST,$errors))){

$msg='Ticket Type '.Format:($_POST).' updated successfully';

}

break;

case 'update':

$category=null;

if($_POST && is_numeric($_POST)) {

$category= new Category($_POST);

if(!$category || !$category->getId()) {

$category=null;

$errors='Unknown Main category'.$id;

}elseif($category->update($_POST,$errors)){

$msg='Main category '.Format:($_POST).' updated successfully';

}elseif(!$errors){

$errors='Error updating the main category. Try again';

}

}

break;

case 'updatesub':

if(!empty($_POST)){ $_POST=$_POST; }

$category=null;

if($_POST && is_numeric($_POST)) {

$category= new Category($_POST);

if(!$category || !$category->getId()) {

$category=null;

$errors='Unknown Sub category'.$id;

}elseif($category->updatesub($_POST,$errors)){

$msg='Sub category '.Format:($_POST).' updated successfully';

}elseif(!$errors){

$errors='Error updating the sub category. Try again';

}

}

break;

case 'updatecats':

if(!empty($_POST)){ $_POST=$_POST; }

if(!empty($_POST)){ $_POST=$_POST; }

$category=null;

if($_POST && is_numeric($_POST)) {

$category= new Category($_POST);

if(!$category || !$category->getId()) {

$category=null;

$errors='Unknown category details'.$id;

}elseif($category->updatecats($_POST,$errors)){

$msg='Category details '.Format:($_POST).' updated successfully';

}elseif(!$errors){

$errors='Error updating the category details. Try again';

}

}

break;

case 'mass_process':

$sql="SELECT * FROM ".TICKET_CATEGORY_TABLE." WHERE ticket_type=".$_REQUEST;

$result=db_query($sql);

$sub=db_num_rows($result);

if($_REQUEST){

$sqlticketcategory="SELECT * FROM ".TICKET_CATEGORY_TABLE." WHERE cat_id=".$_REQUEST;

$resultticketcategory=db_query($sqlticketcategory);

$recordset= mysql_fetch_array($resultticketcategory);

$selectmaincategory="SELECT * FROM ".TICKET_CATEGORY_TABLE." WHERE main_category=".$recordset;

$resultmaincategory=db_query($selectmaincategory);

$maincategory=db_num_rows($resultmaincategory);

$selectsubcategory="SELECT * FROM ".TICKET_CATEGORY_TABLE." WHERE sub_category=".$recordset;

$resultsubcategory=db_query($selectsubcategory);

$subcategory=db_num_rows($resultsubcategory);

if($maincategory>0)

{

$msgerror="Unable to delete main category.Main category associated with some category.";

}else if($subcategory>0)

{ $msgerror="Unable to delete sub category.Sub category associated with some category.";}else{

$sql="DELETE FROM ost_ticket_category WHERE cat_id=".$_REQUEST;

if($result=db_query($sql))

$msg="Record deleted successfully";

}

}

if($sub>0){ $msgerror="Unable to delete ticket type.Ticket type associated with some category." ;}

else{

if($_REQUEST)

{

$sqltickettype="DELETE FROM ".TICKET_TYPE_TABLE." WHERE ticket_typeid=".$_REQUEST;

if($resulttickettype=db_query($sqltickettype))

$msg="Record Deleted sucessfully";

}

}

break;

default:

$errors='Unknown action';

}

break;

C)

Search for the following block of code:

$nav->addSubMenu(array('desc'=>'Add New Dept.','href'=>'admin.php?t=depts&a=new','iconclass'=>'newDepartment'));

break;

Below it add:

case 'cats': $page='catlisting.inc.php';

require_once(INCLUDE_DIR.'class.category.php');

$category=null;

$nav->setTabActive('cats');

$nav->addSubMenu(array('desc'=>'Listing','href'=>'admin.php?t=cats','iconclass'=>'users'));

$nav->addSubMenu(array('desc'=>'Add Ticket Type','href'=>'admin.php?t=cats&a=newtype','iconclass'=>'newuser'));

$nav->addSubMenu(array('desc'=>'Add Main Category','href'=>'admin.php?t=cats&a=maincat','iconclass'=>'newuser'));

$nav->addSubMenu(array('desc'=>'Add sub-category','href'=>'admin.php?t=cats&a=subcat','iconclass'=>'newuser'));

$nav->addSubMenu(array('desc'=>'Add category Details','href'=>'admin.php?t=cats&a=catdtls','iconclass'=>'newuser'));

if(($id=$_REQUEST)) {

$category= new Category($id);

if(!$category->load() && $category->getId()==$id) {

$category=null;

$errors='Unable to fetch info on topic #'.$id;

}

} switch($_REQUEST)

{

case "Sub Category": $page='editsubcategory.inc.php'; break;

case "Main Category": $page='editmaincategory.inc.php'; break;

case "Category Details": $page='editcategorydetails.inc.php'; break;

case "tickettype": $page='edittickettype.inc.php'; break;

}

//$page=($topic or ($_REQUEST=='new' && !$topicID))?'editlisting.php':'editlisting.php';

//$page='';

switch($_REQUEST)

{

case "newtype":

$page='tickettype.inc.php';

break;

case "maincat":

$page='addmaincategory.inc.php';

break;

case "subcat":

$page='addsubcategory.inc.php';

break;

case "catdtls":

$page='addcategorydetails.inc.php';

break;

/*case "category":

$page='catlisting.inc.php';

break; */

}

break;

D) Search for the following code: (around lines 878- 888)

Continued...

<div>

<?if($errors) {?>

<p align="center" id="errormessage"><?=$errors?></p>

<?}elseif($msg) {?>

<p align="center" id="infomessage"><?=$msg?></p>

Replace the Div with:

<div>

<?if($errors) {?>

<p align="center" id="errormessage"><?=$errors?></p>

<?}elseif($msg) {?>

<p align="center" id="infomessage"><?=$msg?></p>

<?}elseif($msgerror) {?>

<p align="center" id="errormessage"><?=$msgerror?></p>

<?}elseif($warn) {?>

<p align="center" id="warnmessage"><?=$warn?></p>

<?}?>

</div>

5. Edit include/class.nav.php

A) Find the following code: (around line 35)

$tabs=array('desc'=>'Departments','href'=>'admin.php?t=depts','title'=>'Departments');

Below it add the following:

$tabs=array('desc'=>'Categories','href'=>'admin.php?t=cats','title'=>'Categories');

6. Edit main.inc.php

A) Find the following code: (around line 137)

define('TIMEZONE_TABLE',TABLE_PREFIX.'timezone');

Replace it with the following code:

define('LINK_TABLE',TABLE_PREFIX.'ticket_link');

define('TICKET_TYPE_TABLE',TABLE_PREFIX.'tickettype');

define('TICKET_CATEGORY_TABLE',TABLE_PREFIX.'ticket_category');

7. Edit scp/css/main.css

A) Find the following (line 142)

#nav ul#main_nav li a {

background(../images/tab.jpg) bottom left no-repeat #fff;

width;

change the width value from 110 to 100

8. Edit include/staff/tickets.inc.php

A) Search for the following code:

$qfrom.=' LEFT JOIN '.TICKET_PRIORITY_TABLE.' pri ON ticket.priority_id=pri.priority_id '.

' LEFT JOIN '.TICKET_LOCK_TABLE.' tlock ON ticket.ticket_id=tlock.ticket_id AND tlock.expire>NOW() '.

' LEFT JOIN '.TICKET_ATTACHMENT_TABLE.' attach ON ticket.ticket_id=attach.ticket_id ';

Below it add the following:

$qfrom.=' LEFT JOIN '.LINK_TABLE.' link ON ticket.ticketID=link.child_ticket_id';

$qwhere.=" AND ISNULL(link.child_ticket_id)";

B) Search for the following code: (around line 400)

<a href="tickets.php?sort=pri&order=<?=$negorder?><?=$qstr?>" title="Sort By Priority <?=$negorder?>">Priority</a></th>

<th width="180" >From</th>

</tr>

<?

Below it add:

function printTree($child_ticket_id,$counter)

{

$sqlchild= "SELECT DISTINCT ticket.ticket_id,lock_id,ticketID,ticket.dept_id,ticket.staff_id,subject,name,email,dept_name ,ticket.status,ticket.source,isoverdue,isanswered,ticket.created,pri.* ,count(attach.attach_id) as attachments ,count(attach.attach_id) as attachments, IF(ticket.reopened is NULL,ticket.created,ticket.reopened) as effective_date FROM ".TICKET_TABLE. " ticket LEFT JOIN ".DEPT_TABLE." dept

ON ticket.dept_id=dept.dept_id

LEFT JOIN ".TICKET_PRIORITY_TABLE." pri

ON ticket.priority_id=pri.priority_id LEFT JOIN ".TICKET_LOCK_TABLE." tlock

ON ticket.ticket_id=tlock.ticket_id

AND tlock.expire>NOW()

LEFT JOIN ".TICKET_ATTACHMENT_TABLE." attach

ON ticket.ticket_id=attach.ticket_id

WHERE ticket.ticketID=".$child_ticket_id;

$childResult= db_query($sqlchild);

$ticketChild= db_fetch_row($childResult);

$tag1=$ticketChild?'assigned':'openticket';

$flag1=null;

if($ticketChild)

$flag1='locked';

elseif($ticketChild)

$flag1='assigned';

elseif($ticketChild)

$flag1='overdue';

$string='';

if($flag1) { $string=' class="Icon'.$flag1.'Ticket" title="'.ucfirst($flag1).' Ticket"' ;}

$string.=' href="tickets.php?id='.$ticketChild.'">'.$ticketChild;

if($ticketChild) $string.='<span class=\'Icon file\'>&nbsp;</span>';

$colArray='<input type="checkbox" name="tids" value="'.$ticketChild.'" onClick="highLight(this.value,this.checked);">';

$colArray='<br/>&nbsp;<a class="Icon '.strtolower($ticketChild).' Ticket" title="'.$ticketChild.' Ticket: '.$ticketChild.'"

href="tickets.php?id='.$ticketChild.'">--'.$ticketChild.'</a>';

$colArray='<br>'.Format:($ticketChild);

$colArray=' <br><a '. $string.' </a>&nbsp;';

$colArray='<br/>'.Format:($ticketChild,30);

$colArray='<br/>'.$ticketChild;

$colArray='<br/>'.Format:($ticketChild,22,strpos($row,'@'));

return $colArray;

}

C) Search for the following code:

$tag=$row?'assigned':'openticket';

$flag=null;

Replace it with:

$col1="";

$col2="";

$col3="";

$col4="";

$col5="";

$col6="";

$col7="";

$showchild=false;

$tid=$row;

$sqlchild= "SELECT child_ticket_id ,parent_ticket_id FROM ".LINK_TABLE. " WHERE parent_ticket_id=".$tid;

$childResult= db_query($sqlchild);

$childResult1= db_query($sqlchild);

$childCount = 0;

while($resItems = db_fetch_row($childResult1))

{

$resultarray=printTree($resItems,$childCount);

if( empty($col1)) $col1= $resultarray; else $col1.=$resultarray;

if( empty($col2)) $col2= $resultarray; else $col2.=$resultarray;

if( empty($col3)) $col3= $resultarray; else $col3.=$resultarray;

if( empty($col4)) $col4= $resultarray; else $col4.=$resultarray;

if( empty($col5)) $col5= $resultarray; else $col5.=$resultarray;

if( empty($col6)) $col6= $resultarray; else $col6.=$resultarray;

if( empty($col7)) $col7= $resultarray; else $col7.=$resultarray;

$childCount++;

$showchild=false;

}

if($childCount==0) $showchild=true;

$tag=$row?'assigned':'openticket';

$flag=null;

D) Search for the following code:

<input type="checkbox" name="tids" value="<?=$row?>" onClick="highLight(this.value,this.checked);">

Below it add:

<?php if($showchild==false) echo $col1; ?>

F) Search for the following code: (around 433 to 435)

href="tickets.php?id=<?=$row?>"><?=$tid?></a></td>

<td align="center" nowrap><?=Format:($row)?></td>

<td><a <?if($flag) { ?> class="Icon <?=$flag?>Ticket" title="<?=ucfirst($flag)?> Ticket" <?}?>

Replace it with:

href="tickets.php?id=<?=$row?>"><?=$tid?></a>

<?php if($showchild==false){echo $col2;}?>

</td>

<td align="center" nowrap>

<?=Format:($row)?>

<?php if($showchild==false){echo $col3;}?>

</td>

<td>

<a <?if($flag) { ?> class="Icon <?=$flag?>Ticket" title="<?=ucfirst($flag)?> Ticket" <?}?>

G) Find the following code: (around lines 437 to 440)

&nbsp;<?=$row?"<span class='Icon file'>&nbsp;</span>":''?></td>

<td nowrap><?=Format:($row,30)?></td>

<td class="nohover" align="center" style="background-color:<?=$row?>;"><?=$row?></td>

<td nowrap><?=Format:($row,22,strpos($row,'@'))?>&nbsp;</td>

Replace it with the following:

&nbsp;<?=$row?"<span class='Icon file'>&nbsp;</span>":''?>

<?php if($showchild==false){echo $col4;}?>

</td>

<td nowrap><?=Format:($row,30)?>

<?php if($showchild==false){echo $col5; ?> <?php } ?>

</td>

<td class="nohover" align="center" style="background-color:<?=$row?>;"><?=$row?>

<?php if($showchild==false){ echo $col6; ?><?php } ?>

</td>

<td nowrap><?=Format:($row,22,strpos($row,'@'))?>&nbsp;

<?php if($showchild==false){echo $col7;?> <?php } ?>

</td>

9. Edit /include/staff/newticket.inc.php

A) Search for the following code: (approx. line 3)

$info=($_POST && $errors)?Format:($_POST)(); //on error...use the post data

Below add the following:

//Ticket categorization code

//get ticket types

$sql = "SELECT ticket_typeid,ticket_type FROM ".TICKET_TYPE_TABLE." WHERE status=1";

$res = db_query($sql);

B) Directly below the code just added there should be the following: ?>

Copy the following code directly below that:

<script>

function getXMLHTTP() { //fuction to return the xml http object

var xmlhttp=false;

try{

xmlhttp=new XMLHttpRequest();

}

catch(e) {

try{

xmlhttp= new ActiveXObject("Microsoft.XMLHTTP");

}

catch(e){

try{

xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");

}

catch(e1){

xmlhttp=false;

}

}

}

return xmlhttp;

}

function getMaincategory(strURL) {

var req = getXMLHTTP();

if (req) {

req.onreadystatechange = function() {

if (req.readyState == 4) {

if (req.status == 200) {

document.getElementById('maincategorydiv').innerHTML=req.responseText;

} else {

alert("There was a problem while using XMLHTTP:\n" + req.statusText);

}

}

}

req.open("GET", strURL, true);

req.send(null);

}

}

function getSubcategory(ticket,maincategory) {

var strURL="ajax.php?api=autoaddsubcat&f=getsubcategory&ticket="+ticket+"&maincategory="+maincategory;

var req = getXMLHTTP();

if (req) {

req.onreadystatechange = function() {

if (req.readyState == 4) {

if (req.status == 200) {

document.getElementById('hiddenfield').value= document.getElementById('main_category').value;

document.getElementById('subcategorydiv').innerHTML=req.responseText;

} else {

alert("There was a problem while using XMLHTTP:\n" + req.statusText);

}

}

}

req.open("GET", strURL, true);

req.send(null);

}

}

function getCategoryDetail(ticket,maincategory,subcategory) {

var strURL="ajax.php?api=autoaddsubcat&f=getcategorydetail&ticket="+ticket+"&maincategory="+maincategory+"&subcategory="+subcategory;

var req = getXMLHTTP();

if (req) {

req.onreadystatechange = function() {

if (req.readyState == 4) {

if (req.status == 200) {

document.getElementById('hiddenfieldsub').value= document.getElementById('sub_category').value;

document.getElementById('categorydetailsdiv').innerHTML=req.responseText;

} else {

alert("There was a problem while using XMLHTTP:\n" + req.statusText);

}

}

}

req.open("GET", strURL, true);

req.send(null);

}

}

function getvalue(){

document.getElementById('hndcatid').value= document.getElementById('selcategorydetails').value;

}

</script>

***Note**** There is more. The last post will have the needed additional files and screencaps

Continued....

C) Search for the following block of code:

<font class="error">&nbsp;<?=$errors?></font></td>

</tr>

Below it add:

Ticket categorization

<tr height=2px><td align="left" colspan=2 >&nbsp;</td</tr>

<tr height=2px><td align="left" colspan=2 ><b>Ticket Categorization</b></td</tr>

<tr>

<td align="left"><b>Ticket Type</b></td>

<td>

<select name="seltickettype" onChange="getMaincategory('ajax.php?api=autoaddsubcat&f=getmaincategory&ticket='+this.value)">

<option value="" selected >Select Ticket Type</option>

<?php

while ($row = db_fetch_array($res)) {

echo "<option value=".$row.">".$row."</option>";

}

?>

</select>

&nbsp;<font class="error"><b>*</b>&nbsp;<?=$errors?></font>

</td>

</tr>

<tr>

<td align="left"><b>Main Category</b></td>

<td><div id="maincategorydiv">

<select name="selmaincategory">

<option value="" selected >Select Main Category</option>

</select>

&nbsp;<font class="error"><b>*</b>&nbsp;<?=$errors?></font></div>

<input type="hidden" value="" id="hiddenfield" name="main_category"/>

</td>

</tr>

<tr>

<td align="left"><b>Sub Category</b></td>

<td><div id="subcategorydiv">

<select name="selsubcategory" >

<option value="" selected >Select Sub Category</option>

</select>

&nbsp;<font class="error"><b>*</b>&nbsp;<?=$errors?></font></div>

<input type="hidden" value="" id="hiddenfieldsub" name="sub_category"/>

</td>

</tr>

<tr>

<td align="left"><b>Category Details</b></td>

<td><div id="categorydetailsdiv">

<select name="selcategorydetails">

<option value="" selected >Select Category Details</option>

</select>

&nbsp;<font class="error"><b>*</b>&nbsp;<?=$errors?></font></div>

<input type="hidden" value="" id="hndcatid" name="hndcatid"/>

</td>

</tr>

Ticket categorization end

10. Edit /scp/css/style.css

A) Go to the bottom of the file and add the following:

table.ticketlinkages {

background-color: #EFEFEF;

border-color:#CCC;

border: 1px solid;

}

table.ticketlinkages td {

border-color:#CCC;

padding-top;

}

table.ticketlinkagesintable {

background-color: #FFFFF3;

border-color:#CCC;

border: 1px solid;

}

table.ticketlinkagesintable td {

border: 0;

padding-top;

}

.linkage{

background-color: #FFFFFF;

border-color:#F2322F;

padding-top;

border-style;

}

******************** DATABASE CHANGES ********************

A) DB Changes:

i) Ticket link table(s):

CREATE TABLE IF NOT EXISTS `ost_ticket_link` (

`id` int(11) NOT NULL AUTO_INCREMENT,

`child_ticket_id` int(11) NOT NULL,

`parent_ticket_id` int(11) NOT NULL,

PRIMARY KEY (`id`)

)

ii) Categorization TABE(S):

CREATE TABLE IF NOT EXISTS `ost_tickettype` (

`ticket_typeid` int(11) NOT NULL AUTO_INCREMENT,

`ticket_type` varchar(250) DEFAULT NULL,

`status` int(11) DEFAULT '1',

PRIMARY KEY (`ticket_typeid`)

) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=27 ;

And

CREATE TABLE IF NOT EXISTS `ost_ticket_category` (

`cat_id` int(11) NOT NULL AUTO_INCREMENT,

`ticket_type` int(11) DEFAULT NULL,

`main_category` varchar(250) DEFAULT NULL,

`sub_category` varchar(250) DEFAULT NULL,

`category_detail` varchar(250) DEFAULT NULL,

`status` int(11) DEFAULT '1',

`created` timestamp NULL DEFAULT CURRENT_TIMESTAMP,

`type_entry` enum('Main Category','Sub Category','Category Details') DEFAULT NULL,

PRIMARY KEY (`cat_id`)

) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=141 ;

ALTER TABLE ost_ticket

ADD COLUMN `category_Id` int(11) NOT NULL;

************ Additional PHP FILES required**************

ALL Additional PHP files needed are in the attached ZIP file. They have been arranged in the folders in which they belong.

Other screenshots attached as well.

osticket-mod1.JPG

osticket-mod2.JPG

osticket-mod3.JPG

[modfiles.zip](https://forum.osticket.com/assets/files/migrated/2/16224d4a38df03761d3260e398f9d5c.zip)

I will take a look at it Monday morning. I am pretty sure I know where the error is (but no guarantees just yet).

Thank you for this addon.

I have the following error, maybe I entered something wrong.

Parse error: syntax error, unexpected '}' in /customers/sbshasselt.be/sbshasselt.be/httpd.www/helpdesk/scp/tickets.php on line 514

Is it possible to look at my file?

Thanks

Hey there,

I took a look at the PHP file you posted. In the second post of the code above

scp/tickets.php (point F)

It looks like the If statement was not overwritten but rather removed. I have gone through and compared the file you uploaded and added the needed code.

(the new code I have added starts at line 512)- The Zip file with the new changes is uploaded.

[tickets.zip](https://forum.osticket.com/assets/files/migrated/7/12f7a0cd402bf794b3d5f7b7bebab44.zip)

Odd SQL error

Hi,

I've just added this to a fairly clean installation (I've added the Reports MOD and Simple Time spent mod). But once I've added this mod whenever I bring up any ticket view I get this error in the system log and can't quite figure out why.

Unknown column 'link.child_ticket_id' in 'where clause'

Any ideas what could be causing it. I've been trough the process twice so pretty sure I've not made any typo's etc on it

Hi,

I've just added this to a fairly clean installation (I've added the Reports MOD and Simple Time spent mod). But once I've added this mod whenever I bring up any ticket view I get this error in the system log and can't quite figure out why.

Unknown column 'link.child_ticket_id' in 'where clause'

Any ideas what could be causing it. I've been trough the process twice so pretty sure I've not made any typo's etc on it

Is the error you're getting after adding a new ticket or is it when opening an existing ticket. I ask because I am unable to duplicate the error in my install. I think the error is being kicked back from around line 518 in scp/tickets.php

if(!$thisuser->isAdmin()){

$sql.=' WHERE ticket.dept_id IN('.implode(',',$thisuser->getDepts()).') OR ticket.staff_id='.db_input($thisuser->getId());

}

else

$sql.= <STRONG><s>**</s>' WHERE ISNULL(link.child_ticket_id)'<e>**</e></STRONG>;

Did you add the link table to the Osticket DB?

If not the code is below:

CREATE TABLE IF NOT EXISTS `ost_ticket_link` (

`id` int(11) NOT NULL AUTO_INCREMENT,

`child_ticket_id` int(11) NOT NULL,

`parent_ticket_id` int(11) NOT NULL,

PRIMARY KEY (`id`)

)

15 days later

Hey there,

I took a look at the PHP file you posted. In the second post of the code above

scp/tickets.php (point F)

It looks like the If statement was not overwritten but rather removed. I have gone through and compared the file you uploaded and added the needed code.

(the new code I have added starts at line 512)- The Zip file with the new changes is uploaded.

@Rich_C

Hello, thank you for all your hard work on this mod

Just small correction, in attached zip file (tickets.php) on line 512 need to delete one surplus line: if(!$thisuser->isAdmin()){

My problem is that almost everything working fine except few things, like Departments tab don't work, or when I click on Departments it's open Categories tab? And is this MOD finished, because don't know how to use ticket categorisation, or that have to be done? Like, right now I can't see how to filter view or search tickets by Category?

Best regards, and thank you!

@Rich_C

Hello, thank you for all your hard work on this mod

Just small correction, in attached zip file (tickets.php) on line 512 need to delete one surplus line: if(!$thisuser->isAdmin()){

My problem is that almost everything working fine except few things, like Departments tab don't work, or when I click on Departments it's open Categories tab? And is this MOD finished, because don't know how to use ticket categorisation, or that have to be done? Like, right now I can't see how to filter view or search tickets by Category?

Best regards, and thank you

I added this code and mod based on a completely un-modded install. I just re-opened a new test site and re-added the mod based on the instructions above and it works without issue. This includes the departments tab.

To add new Categories (this mod implements a 4-tier structure) you need to go to the admin panel and click the 'Categories Tab' which should be at the far right. Once you get there you should see Listing (which is a list of all categories and Sub-categories) and to the right and add button for each layer of categorization.

I had not thought of the need to search by ticket category but it is something I can look into.

Please PM me you Admin page PHP code and I will compare it to the installation I have working to try and help further.

6 months later

It all disappeared!

I followed the instructions but when I go to the /scp page it's just a white screen. Any ideas where to begin in troubleshooting this?

Augustus

You should check your php error log and see what the error being thrown is. It could be as simple as a single typo. You can post the error here if you do not know how to read error messages and we can tell you where to look.

You should check your php error log and see what the error being thrown is. It could be as simple as a single typo. You can post the error here if you do not know how to read error messages and we can tell you where to look.

Thanks that helped.

Great Mod! I still need a little help though...

I have an issue with adding the sub categories. When I go to the Categories tab and try to enter a sub category, the main category field disappears after I select a ticket type. This also happens under the ticket categorization, I select the ticket type and then the main category field goes away. I have included screenshots.

CSC_error2.jpg

CSC_error.jpg

Hello there.

I am very sorry for not being able to get back to you. I am just starting to port this over to 1.7. I am also working on my AD mod which auto-fills in details for client tickets for them to speed up the ticket submission process.

I had the same error you're having there. I believe I cleared my cache and it cleared the issue. I had to do that a bunch of times as the code was changing often when it was being built. Aside form that double check the instructions again and make sure the cases, spaces etc. are all 100%.

I appreciate any feedback as getting input from multiple sources will give me different perspectives on the MOD.

Rich_C

I tried clearing the browser cache but that didn't seem to do it. I will reinstall the mod and see if that works. I thought I copied and pasted the parts into the files. I have a clean install saved so I can do it as often as needed.

Thanks for your continued supported with the Mod.