Merge pull request #18128 from evarisk-theo/add-ticket-categories-functions

add: ticket categories functions
This commit is contained in:
Laurent Destailleur 2021-07-14 02:21:13 +02:00 committed by GitHub
commit 7f2cdbf96e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 284 additions and 4 deletions

View File

@ -34,6 +34,7 @@
require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
require_once DOL_DOCUMENT_ROOT.'/ticket/class/ticket.class.php';
require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.class.php';
require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
@ -56,6 +57,7 @@ class Categorie extends CommonObject
const TYPE_WAREHOUSE = 'warehouse';
const TYPE_ACTIONCOMM = 'actioncomm';
const TYPE_WEBSITE_PAGE = 'website_page';
const TYPE_TICKET = 'ticket';
/**
* @var string String with name of icon for myobject. Must be the part after the 'object_' into object_myobject.png
@ -78,7 +80,8 @@ class Categorie extends CommonObject
'bank_line' => 8,
'warehouse' => 9,
'actioncomm' => 10,
'website_page' => 11
'website_page' => 11,
'ticket' => 12
);
/**
@ -98,7 +101,8 @@ class Categorie extends CommonObject
8 => 'bank_line',
9 => 'warehouse',
10 => 'actioncomm',
11 => 'website_page'
11 => 'website_page',
12 => 'ticket'
);
/**
@ -141,7 +145,8 @@ class Categorie extends CommonObject
'project' => 'Project',
'warehouse'=> 'Entrepot',
'actioncomm' => 'ActionComm',
'website_page' => 'WebsitePage'
'website_page' => 'WebsitePage',
'ticket' => 'Ticket'
);
/**
@ -234,6 +239,8 @@ class Categorie extends CommonObject
* @see Categorie::TYPE_WAREHOUSE
* @see Categorie::TYPE_ACTIONCOMM
* @see Categorie::TYPE_WEBSITE_PAGE
* @see Categorie::TYPE_TICKET
*/
public $type;

View File

@ -4454,7 +4454,6 @@ class Form
*/
public function selectEstablishments($selected = '', $htmlname = 'entity', $status = 0, $filtre = '', $useempty = 0, $moreattrib = '')
{
// phpcs:enable
global $langs, $conf;
$langs->load("admin");
@ -6582,6 +6581,213 @@ class Form
return;
}
/**
* Return list of tickets in Ajax if Ajax activated or go to selectTicketsList
*
* @param int $selected Preselected tickets
* @param string $htmlname Name of HTML select field (must be unique in page).
* @param string $filtertype To add a filter
* @param int $limit Limit on number of returned lines
* @param int $status Ticket status
* @param string $selected_input_value Value of preselected input text (for use with ajax)
* @param int $hidelabel Hide label (0=no, 1=yes, 2=show search icon (before) and placeholder, 3 search icon after)
* @param array $ajaxoptions Options for ajax_autocompleter
* @param int $socid Thirdparty Id (to get also price dedicated to this customer)
* @param string $showempty '' to not show empty line. Translation key to show an empty line. '1' show empty line with no text.
* @param int $forcecombo Force to use combo box
* @param string $morecss Add more css on select
* @param array $selected_combinations Selected combinations. Format: array([attrid] => attrval, [...])
* @param string $nooutput No print, return the output into a string
* @return void|string
*/
public function selectTickets($selected = '', $htmlname = 'ticketid', $filtertype = '', $limit = 0, $status = 1, $selected_input_value = '', $hidelabel = 0, $ajaxoptions = array(), $socid = 0, $showempty = '1', $forcecombo = 0, $morecss = '', $selected_combinations = null, $nooutput = 0)
{
global $langs, $conf;
$out = '';
// check parameters
if (is_null($ajaxoptions)) $ajaxoptions = array();
if (!empty($conf->use_javascript_ajax) && !empty($conf->global->TICKET_USE_SEARCH_TO_SELECT)) {
$placeholder = '';
if ($selected && empty($selected_input_value)) {
require_once DOL_DOCUMENT_ROOT.'/ticket/class/ticket.class.php';
$tickettmpselect = new Ticket($this->db);
$tickettmpselect->fetch($selected);
$selected_input_value = $tickettmpselect->ref;
unset($tickettmpselect);
}
$out .= ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT.'/ticket/ajax/tickets.php', $urloption, $conf->global->PRODUIT_USE_SEARCH_TO_SELECT, 1, $ajaxoptions);
if (empty($hidelabel)) $out .= $langs->trans("RefOrLabel").' : ';
elseif ($hidelabel > 1) {
$placeholder = ' placeholder="'.$langs->trans("RefOrLabel").'"';
if ($hidelabel == 2) {
$out .= img_picto($langs->trans("Search"), 'search');
}
}
$out .= '<input type="text" class="minwidth100" name="search_'.$htmlname.'" id="search_'.$htmlname.'" value="'.$selected_input_value.'"'.$placeholder.' '.(!empty($conf->global->PRODUCT_SEARCH_AUTOFOCUS) ? 'autofocus' : '').' />';
if ($hidelabel == 3) {
$out .= img_picto($langs->trans("Search"), 'search');
}
} else {
$out .= $this->selectTicketsList($selected, $htmlname, $filtertype, $limit, $status, 0, $socid, $showempty, $forcecombo, $morecss);
}
if (empty($nooutput)) print $out;
else return $out;
}
/**
* Return list of tickets.
* Called by selectTickets.
*
* @param int $selected Preselected ticket
* @param string $htmlname Name of select html
* @param string $filtertype Filter on ticket type
* @param int $limit Limit on number of returned lines
* @param string $filterkey Filter on product
* @param int $status Ticket status
* @param int $outputmode 0=HTML select string, 1=Array
* @param string $showempty '' to not show empty line. Translation key to show an empty line. '1' show empty line with no text.
* @param int $forcecombo Force to use combo box
* @param string $morecss Add more css on select
* @return array Array of keys for json
*/
public function selectTicketsList($selected = '', $htmlname = 'ticketid', $filtertype = '', $limit = 20, $filterkey = '', $status = 1, $outputmode = 0, $showempty = '1', $forcecombo = 0, $morecss = '')
{
global $langs, $conf, $user, $db;
$out = '';
$outarray = array();
$selectFields = " p.rowid, p.ref, p.message";
$sql = "SELECT ";
$sql .= $selectFields;
$sql .= " FROM ".MAIN_DB_PREFIX."ticket as p";
$sql .= ' WHERE p.entity IN ('.getEntity('ticket').')';
// Add criteria on ref/label
if ($filterkey != '') {
$sql .= ' AND (';
$prefix = empty($conf->global->TICKET_DONOTSEARCH_ANYWHERE) ? '%' : ''; // Can use index if PRODUCT_DONOTSEARCH_ANYWHERE is on
// For natural search
$scrit = explode(' ', $filterkey);
$i = 0;
if (count($scrit) > 1) $sql .= "(";
foreach ($scrit as $crit) {
if ($i > 0) $sql .= " AND ";
$sql .= "(p.ref LIKE '".$this->db->escape($prefix.$crit)."%' OR p.label LIKE '".$this->db->escape($prefix.$crit)."%'";
$sql .= ")";
$i++;
}
if (count($scrit) > 1) $sql .= ")";
$sql .= ')';
}
$sql .= $this->db->plimit($limit, 0);
// Build output string
dol_syslog(get_class($this)."::selectTicketsList search tickets", LOG_DEBUG);
$result = $this->db->query($sql);
if ($result) {
require_once DOL_DOCUMENT_ROOT.'/ticket/class/ticket.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/ticket.lib.php';
$num = $this->db->num_rows($result);
$events = null;
if (!$forcecombo) {
include_once DOL_DOCUMENT_ROOT.'/core/lib/ajax.lib.php';
$out .= ajax_combobox($htmlname, $events, $conf->global->TICKET_USE_SEARCH_TO_SELECT);
}
$out .= '<select class="flat'.($morecss ? ' '.$morecss : '').'" name="'.$htmlname.'" id="'.$htmlname.'">';
$textifempty = '';
// Do not use textifempty = ' ' or '&nbsp;' here, or search on key will search on ' key'.
//if (! empty($conf->use_javascript_ajax) || $forcecombo) $textifempty='';
if (!empty($conf->global->TICKET_USE_SEARCH_TO_SELECT)) {
if ($showempty && !is_numeric($showempty)) $textifempty = $langs->trans($showempty);
else $textifempty .= $langs->trans("All");
} else {
if ($showempty && !is_numeric($showempty)) $textifempty = $langs->trans($showempty);
}
if ($showempty) $out .= '<option value="0" selected>'.$textifempty.'</option>';
$i = 0;
while ($num && $i < $num) {
$opt = '';
$optJson = array();
$objp = $this->db->fetch_object($result);
$this->constructTicketListOption($objp, $opt, $optJson, $selected, $filterkey);
// Add new entry
// "key" value of json key array is used by jQuery automatically as selected value
// "label" value of json key array is used by jQuery automatically as text for combo box
$out .= $opt;
array_push($outarray, $optJson);
$i++;
}
$out .= '</select>';
$this->db->free($result);
if (empty($outputmode)) return $out;
return $outarray;
} else {
dol_print_error($db);
}
}
/**
* constructTicketListOption.
* This define value for &$opt and &$optJson.
*
* @param resource $objp Result set of fetch
* @param string $opt Option (var used for returned value in string option format)
* @param string $optJson Option (var used for returned value in json format)
* @param string $selected Preselected value
* @param string $filterkey Filter key to highlight
* @return void
*/
protected function constructTicketListOption(&$objp, &$opt, &$optJson, $selected, $filterkey = '')
{
global $langs, $conf, $user, $db;
$outkey = '';
$outval = '';
$outref = '';
$outlabel = '';
$outtype = '';
$label = $objp->label;
$outkey = $objp->rowid;
$outref = $objp->ref;
$outlabel = $objp->label;
$outtype = $objp->fk_product_type;
$opt = '<option value="'.$objp->rowid.'"';
$opt .= ($objp->rowid == $selected) ? ' selected' : '';
$opt .= '>';
$opt .= $objp->ref;
$objRef = $objp->ref;
if (!empty($filterkey) && $filterkey != '') $objRef = preg_replace('/('.preg_quote($filterkey, '/').')/i', '<strong>$1</strong>', $objRef, 1);
$outval .= $objRef;
$opt .= "</option>\n";
$optJson = array('key'=>$outkey, 'value'=>$outref, 'type'=>$outtypem);
}
/**
* Generic method to select a component from a combo list.

View File

@ -272,6 +272,15 @@ class FormTicket
print '</td></tr>';
}
//Categories
if ($conf->categorie->enabled) {
// Categories
print '<tr><td>'.$langs->trans("Categories").'</td><td colspan="3">';
$cate_arbo = $form->select_all_categories(Categorie::TYPE_TICKET, '', 'parent', 64, 0, 1);
print img_picto('', 'category').$form->multiselectarray('categories', $cate_arbo, GETPOST('categories', 'array'), '', 0, 'quatrevingtpercent widthcentpercentminusx', 0, 0);
print "</td></tr>";
}
// Attached files
if (!empty($this->withfile)) {
// Define list of attached files

View File

@ -283,6 +283,19 @@ class modTicket extends DolibarrModules
'target' => '',
'user' => 0);
$r++;
$this->menu[$r] = array('fk_menu' => 'fk_mainmenu=ticket,fk_leftmenu=ticket',
'type' => 'left',
'titre' => 'Categories',
'mainmenu' => 'ticket',
'url' => '/categories/index.php?type=12',
'langs' => 'ticket',
'position' => 107,
'enabled' => '$conf->categorie->enabled',
'perms' => '$user->rights->ticket->read',
'target' => '',
'user' => 0);
$r++;
}
/**

View File

@ -2499,6 +2499,51 @@ class Ticket extends CommonObject
return array('listofpaths'=>$listofpaths, 'listofnames'=>$listofnames, 'listofmimes'=>$mimetype);
}
/**
* Sets object to supplied categories.
*
* Deletes object from existing categories not supplied.
* Adds it to non existing supplied categories.
* Existing categories are left untouch.
*
* @param int[]|int $categories Category or categories IDs
* @return void
*/
public function setCategories($categories)
{
// Handle single category
if (!is_array($categories)) {
$categories = array($categories);
}
// Get current categories
include_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
$c = new Categorie($this->db);
$existing = $c->containing($this->id, Categorie::TYPE_TICKET, 'id');
// Diff
if (is_array($existing)) {
$to_del = array_diff($existing, $categories);
$to_add = array_diff($categories, $existing);
} else {
$to_del = array(); // Nothing to delete
$to_add = $categories;
}
// Process
foreach ($to_del as $del) {
if ($c->fetch($del) > 0) {
$c->del_type($this, Categorie::TYPE_TICKET);
}
}
foreach ($to_add as $add) {
if ($c->fetch($add) > 0) {
$c->add_type($this, Categorie::TYPE_TICKET);
}
}
return;
}
/**
* Add new message on a ticket (private/public area). Can also send it be email if GETPOST('send_email', 'int') is set.