';
@@ -571,6 +606,12 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea
print '' . "\n";
}
+ if (! empty($debuginfo))
+ {
+ print info_admin($debuginfo);
+ }
+
+
// Select mail models is same action as presend
if (GETPOST('modelselected')) {
$action = 'presend';
diff --git a/htdocs/admin/ticket.php b/htdocs/admin/ticket.php
index 052e11f1ced..def9a30fc8d 100644
--- a/htdocs/admin/ticket.php
+++ b/htdocs/admin/ticket.php
@@ -66,7 +66,7 @@ if ($action == 'updateMask') {
// TODO Verifier si module numerotation choisi peut etre active
// par appel methode canBeActivated
- dolibarr_set_const($db, "TICKETSUP_ADDON", $value, 'chaine', 0, '', $conf->entity);
+ dolibarr_set_const($db, "TICKET_ADDON", $value, 'chaine', 0, '', $conf->entity);
} elseif ($action == 'setvar') {
include_once DOL_DOCUMENT_ROOT . "/core/lib/files.lib.php";
@@ -256,7 +256,7 @@ foreach ($dirmodels as $reldir) {
print '
' . "\n";
print '
';
- if ($conf->global->TICKETSUP_ADDON == 'mod_' . $classname) {
+ if ($conf->global->TICKET_ADDON == 'mod_' . $classname) {
print img_picto($langs->trans("Activated"), 'switch_on');
} else {
print '' . img_picto($langs->trans("Disabled"), 'switch_off') . '';
diff --git a/htdocs/core/class/conf.class.php b/htdocs/core/class/conf.class.php
index 12d6b337fd0..861c273e28a 100644
--- a/htdocs/core/class/conf.class.php
+++ b/htdocs/core/class/conf.class.php
@@ -447,7 +447,7 @@ class Conf
if (empty($this->global->SOCIETE_CODECOMPTA_ADDON)) $this->global->SOCIETE_CODECOMPTA_ADDON="mod_codecompta_panicum";
if (empty($this->global->CHEQUERECEIPTS_ADDON)) $this->global->CHEQUERECEIPTS_ADDON='mod_chequereceipt_mint';
- if (empty($conf->global->TICKETSUP_ADDON)) $this->global->TICKETSUP_ADDON='mod_ticket_simple';
+ if (empty($conf->global->TICKET_ADDON)) $this->global->TICKET_ADDON='mod_ticket_simple';
// Security
if (empty($this->global->USER_PASSWORD_GENERATED)) $this->global->USER_PASSWORD_GENERATED='standard'; // Default password generator
diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php
index 61892f694d7..a54bfc4492d 100644
--- a/htdocs/core/class/html.form.class.php
+++ b/htdocs/core/class/html.form.class.php
@@ -5828,7 +5828,7 @@ class Form
* Note: Do not apply langs->trans function on returned content, content may be entity encoded twice.
*
* @param string $htmlname Name of html select area. Must start with "multi" if this is a multiselect
- * @param array $array Array (key => value)
+ * @param array $array Array like array(key => value) or array(key=>array('label'=>..., 'data-...'=>...))
* @param string|string[] $id Preselected key or preselected keys for multiselect
* @param int|string $show_empty 0 no empty value allowed, 1 or string to add an empty value into list (key is -1 and value is '' or ' ' if 1, key is -1 and value is text if string), <0 to add an empty value with key that is this value.
* @param int $key_in_label 1 to show key into label with format "[key] value"
@@ -5889,7 +5889,8 @@ class Form
{
foreach($array as $key => $value)
{
- $array[$key]=$langs->trans($value);
+ if (! is_array($value)) $array[$key]=$langs->trans($value);
+ else $array[$key]['label']=$langs->trans($value['label']);
}
}
@@ -5897,8 +5898,11 @@ class Form
if ($sort == 'ASC') asort($array);
elseif ($sort == 'DESC') arsort($array);
- foreach($array as $key => $value)
+ foreach($array as $key => $tmpvalue)
{
+ if (is_array($tmpvalue)) $value=$tmpvalue['label'];
+ else $value = $tmpvalue;
+
$disabled=''; $style='';
if (! empty($disablebademail))
{
@@ -5926,6 +5930,13 @@ class Form
$out.=$style.$disabled;
if ($id != '' && $id == $key && ! $disabled) $out.=' selected'; // To preselect a value
if ($nohtmlescape) $out.=' data-html="'.dol_escape_htmltag($selectOptionValue).'"';
+ if (is_array($tmpvalue))
+ {
+ foreach($tmpvalue as $keyforvalue => $valueforvalue)
+ {
+ if (preg_match('/^data-/', $keyforvalue)) $out.=' '.$keyforvalue.'="'.$valueforvalue.'"';
+ }
+ }
$out.='>';
//var_dump($selectOptionValue);
$out.=$selectOptionValue;
diff --git a/htdocs/emailcollector/class/emailcollector.class.php b/htdocs/emailcollector/class/emailcollector.class.php
index e0f745dabec..386f5de9a91 100644
--- a/htdocs/emailcollector/class/emailcollector.class.php
+++ b/htdocs/emailcollector/class/emailcollector.class.php
@@ -27,6 +27,7 @@ require_once DOL_DOCUMENT_ROOT . '/contact/class/contact.class.php';
require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
require_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php';
require_once DOL_DOCUMENT_ROOT . '/compta/facture/class/facture.class.php';
+require_once DOL_DOCUMENT_ROOT . '/ticket/class/ticket.class.php';
/**
@@ -172,6 +173,8 @@ class EmailCollector extends CommonObject
public $filters;
public $actions;
+ public $debuginfo;
+
/**
* Constructor
@@ -737,7 +740,7 @@ class EmailCollector extends CommonObject
$errorforthisaction = 0;
// Overwrite values with values extracted from source email
- // $this->actionparam = 'opportunity_status=123;abc=REGEX:BODY:....'
+ // $this->actionparam = 'opportunity_status=123;abc=EXTRACT:BODY:....'
$arrayvaluetouse = dolExplodeIntoArray($actionparam, ';', '=');
foreach($arrayvaluetouse as $propertytooverwrite => $valueforproperty)
{
@@ -761,13 +764,13 @@ class EmailCollector extends CommonObject
$regexstring='';
//$transformationstring='';
$regforregex=array();
- if (preg_match('/^REGEX:([a-zA-Z0-9]+):(.*):([^:])$/', $valueforproperty, $regforregex))
+ if (preg_match('/^EXTRACT:([a-zA-Z0-9]+):(.*):([^:])$/', $valueforproperty, $regforregex))
{
$sourcefield=$regforregex[1];
$regexstring=$regforregex[2];
//$transofrmationstring=$regforregex[3];
}
- elseif (preg_match('/^REGEX:([a-zA-Z0-9]+):(.*)$/', $valueforproperty, $regforregex))
+ elseif (preg_match('/^EXTRACT:([a-zA-Z0-9]+):(.*)$/', $valueforproperty, $regforregex))
{
$sourcefield=$regforregex[1];
$regexstring=$regforregex[2];
@@ -789,7 +792,7 @@ class EmailCollector extends CommonObject
// Nothing can be done for this param
}
}
- elseif (preg_match('/^VALUE:(.*)$/', $valueforproperty, $reg))
+ elseif (preg_match('/^SET:(.*)$/', $valueforproperty, $reg))
{
$object->$tmpproperty = $reg[1];
}
@@ -820,7 +823,7 @@ class EmailCollector extends CommonObject
dol_syslog("EmailCollector::doCollectOneCollector start", LOG_DEBUG);
- $langs->loadLangs(array("project", "companies", "mails", "errors"));
+ $langs->loadLangs(array("project", "companies", "mails", "errors", "ticket"));
$error = 0;
$this->output = '';
@@ -866,8 +869,14 @@ class EmailCollector extends CommonObject
return -3;
}
+ // $conf->global->MAIL_PREFIX_FOR_EMAIL_ID must be defined
+ $host=dol_getprefix('email');
+
+ // Define the IMAP search string
+ // See https://tools.ietf.org/html/rfc3501#section-6.4.4
//$search='ALL';
- $search='UNDELETED';
+ $search='UNDELETED NOT DRAFT';
+ $searchhead='';
$searchfilterdoltrackid=0;
$searchfilternodoltrackid=0;
foreach($this->filters as $rule)
@@ -880,10 +889,15 @@ class EmailCollector extends CommonObject
if ($rule['type'] == 'from') $search.=($search?' ':'').'FROM "'.str_replace('"', '', $rule['rulevalue']).'"';
if ($rule['type'] == 'subject') $search.=($search?' ':'').'SUBJECT "'.str_replace('"', '', $rule['rulevalue']).'"';
if ($rule['type'] == 'body') $search.=($search?' ':'').'BODY "'.str_replace('"', '', $rule['rulevalue']).'"';
+ if ($rule['type'] == 'header') $search.=($search?' ':'').'HEADER '.$rule['rulevalue'];
+
if ($rule['type'] == 'seen') $search.=($search?' ':'').'SEEN';
if ($rule['type'] == 'unseen') $search.=($search?' ':'').'UNSEEN';
- if ($rule['type'] == 'withtrackingid') $searchfilterdoltrackid++;
- if ($rule['type'] == 'withouttrackingid') $searchfilternodoltrackid++;
+ if ($rule['type'] == 'smaller') $search.=($search?' ':'').'SMALLER "'.str_replace('"', '', $rule['rulevalue']).'"';
+ if ($rule['type'] == 'larger') $search.=($search?' ':'').'LARGER "'.str_replace('"', '', $rule['rulevalue']).'"';
+
+ if ($rule['type'] == 'withtrackingid') { $searchfilterdoltrackid++; $searchhead.='/References.*@'.preg_quote($host, '/').'/'; }
+ if ($rule['type'] == 'withouttrackingid') { $searchfilternodoltrackid++; $searchhead.='! /References.*@'.preg_quote($host, '/').'/';}
}
if (empty($targetdir)) // Use last date as filter if there is no targetdir defined.
@@ -916,11 +930,7 @@ class EmailCollector extends CommonObject
$headers = array_combine($matches[1], $matches[2]);
//var_dump($headers);
- // $conf->global->MAIL_PREFIX_FOR_EMAIL_ID must be defined
- $host=dol_getprefix('email');
-
// If there is a filter on trackid
- //var_dump($host);exit;
if ($searchfilterdoltrackid > 0)
{
//if (empty($headers['X-Dolibarr-TRACKID'])) continue;
@@ -1101,8 +1111,10 @@ class EmailCollector extends CommonObject
$contactid = 0; $thirdpartyid = 0; $projectid = 0;
- // Analyze TrackId in field References
- // For example: References: <1542377954.SMTPs-dolibarr-thi649@8f6014fde11ec6cdec9a822234fc557e>
+ // Analyze TrackId in field References. For example:
+ // References: <1542377954.SMTPs-dolibarr-thi649@8f6014fde11ec6cdec9a822234fc557e>
+ // References: <1542377954.SMTPs-dolibarr-tic649@8f6014fde11ec6cdec9a822234fc557e>
+ // References: <1542377954.SMTPs-dolibarr-abc649@8f6014fde11ec6cdec9a822234fc557e>
$trackid = '';
$reg=array();
if (! empty($headers['References']) && preg_match('/dolibarr-([a-z]+)([0-9]+)@'.preg_quote($host, '/').'/', $headers['References'], $reg))
@@ -1136,6 +1148,11 @@ class EmailCollector extends CommonObject
$objectid = $reg[1];
$objectemail = new User($this->db);
}
+ if ($reg[0] == 'tic')
+ {
+ $objectid = $reg[1];
+ $objectemail = new Ticket($this->db);
+ }
if (is_object($objectemail))
{
@@ -1233,7 +1250,7 @@ class EmailCollector extends CommonObject
if (empty($operation['actionparam']))
{
$errorforactions++;
- $this->error = "Action loadthirdparty or loadandcreatethirdparty has empty parameter. Must be 'VALUE:xxx' or 'REGEX:(body|subject):regex' to define how to extract data";
+ $this->error = "Action loadthirdparty or loadandcreatethirdparty has empty parameter. Must be 'SET:xxx' or 'EXTRACT:(body|subject):regex' to define how to extract data";
$this->errors[] = $this->error;
}
else
@@ -1241,7 +1258,7 @@ class EmailCollector extends CommonObject
$actionparam = $operation['actionparam'];
$nametouseforthirdparty='';
- // $this->actionparam = 'VALUE:aaa' or 'REGEX:BODY:....'
+ // $this->actionparam = 'SET:aaa' or 'EXTRACT:BODY:....'
$arrayvaluetouse = dolExplodeIntoArray($actionparam, ';', '=');
foreach($arrayvaluetouse as $propertytooverwrite => $valueforproperty)
{
@@ -1250,7 +1267,7 @@ class EmailCollector extends CommonObject
$regexstring='';
$regforregex=array();
- if (preg_match('/^REGEX:([a-zA-Z0-9]+):(.*)$/', $valueforproperty, $regforregex))
+ if (preg_match('/^EXTRACT:([a-zA-Z0-9]+):(.*)$/', $valueforproperty, $regforregex))
{
$sourcefield=$regforregex[1];
$regexstring=$regforregex[2];
@@ -1273,7 +1290,7 @@ class EmailCollector extends CommonObject
}
//var_dump($sourcestring); var_dump($regexstring);var_dump($nametouseforthirdparty);exit;
}
- elseif (preg_match('/^VALUE:(.*)$/', $valueforproperty, $reg))
+ elseif (preg_match('/^SET:(.*)$/', $valueforproperty, $reg))
{
$nametouseforthirdparty = $reg[1];
}
@@ -1338,6 +1355,19 @@ class EmailCollector extends CommonObject
{
$actioncode = 'EMAIL_IN';
+ if ($projectstatic->id > 0)
+ {
+ if ($projectfoundby) $messagetext .= ' - Project found from '.$projectfoundby;
+ }
+ if ($thirdpartystatic->id > 0)
+ {
+ if ($thirdpartyfoundby) $messagetext .= ' - Third party found from '.$thirdpartyfoundby;
+ }
+ if ($contactstatic->id > 0)
+ {
+ if ($contactfoundby) $messagetext .= ' - Contact/address found from '.$contactfoundby;
+ }
+
// Insert record of emails sent
$actioncomm = new ActionComm($this->db);
@@ -1471,6 +1501,90 @@ class EmailCollector extends CommonObject
}
}
}
+ // Create event
+ elseif ($operation['type'] == 'ticket')
+ {
+ $note_private = $langs->trans("TicketCreatedByEmailCollector", $msgid);
+ $tickettocreate = new Ticket($this->db);
+ if ($thirdpartystatic->id > 0)
+ {
+ $tickettocreate->socid = $thirdpartystatic->id;
+ if ($thirdpartyfoundby) $note_private .= ' - Third party found from '.$thirdpartyfoundby;
+ }
+ if ($contactstatic->id > 0)
+ {
+ $tickettocreate->contact_id = $contactstatic->id;
+ if ($contactfoundby) $note_private .= ' - Contact/address found from '.$contactfoundby;
+ }
+
+ $tickettocreate->title = $subject;
+ $tickettocreate->type_code = 0;
+ $tickettocreate->category_code = 0;
+ $tickettocreate->severity_code = 0;
+ $tickettocreate->origin_email = $fromstring;
+ $tickettocreate->fk_user_create = $user->id;
+ $tickettocreate->entity = $conf->entity;
+ $tickettocreate->datec = $date;
+ $tickettocreate->fk_project = $projectstatic->id;
+ $tickettocreate->fk_soc = $thirdpartystatic->id;
+ $tickettocreate->notify_tiers_at_create = 0;
+ //$tickettocreate->fk_contact = $contactstatic->id;
+
+ // Get next project Ref
+ $defaultref='';
+ $modele = empty($conf->global->TICKET_ADDON)?'mod_ticket_simple':$conf->global->TICKET_ADDON;
+
+ // Search template files
+ $file=''; $classname=''; $filefound=0; $reldir='';
+ $dirmodels=array_merge(array('/'), (array) $conf->modules_parts['models']);
+ foreach($dirmodels as $reldir)
+ {
+ $file=dol_buildpath($reldir."core/modules/ticket/".$modele.'.php', 0);
+ if (file_exists($file))
+ {
+ $filefound=1;
+ $classname = $modele;
+ break;
+ }
+ }
+
+ if ($filefound)
+ {
+ $result=dol_include_once($reldir."core/modules/ticket/".$modele.'.php');
+ $modTicket = new $classname;
+
+ $defaultref = $modTicket->getNextValue(($thirdpartystatic->id > 0 ? $thirdpartystatic : null), $tickettocreate);
+ }
+
+ $tickettocreate->ref = $defaultref;
+
+ // Overwrite values with values extracted from source email
+ $errorforthisaction = $this->overwritePropertiesOfObject($tickettocreate, $operation['actionparam'], $messagetext, $subject);
+
+ if ($errorforthisaction)
+ {
+ $errorforactions++;
+ }
+ else
+ {
+ if (is_numeric($tickettocreate->ref) && $tickettocreate->ref <= 0)
+ {
+ $errorforactions++;
+ $this->error = 'Failed to create ticket: Can\'t get a valid value for ticket Ref';
+ }
+ else
+ {
+ // Create project
+ $result = $tickettocreate->create($user);
+ if ($result <= 0)
+ {
+ $errorforactions++;
+ $this->error = 'Failed to create ticket: '.$langs->trans($tickettocreate->error);
+ $this->errors = $tickettocreate->errors;
+ }
+ }
+ }
+ }
if (! $errorforactions)
{
@@ -1537,6 +1651,9 @@ class EmailCollector extends CommonObject
$this->datelastresult = $now;
$this->lastresult = $output;
+ $this->debuginfo = 'IMAP search string used : '.$search;
+ if ($searchhead) $this->debuginfo .= ' Then search string into email header : '.$searchhead;
+
if (! empty($this->errors)) $this->lastresult.= " - ".join(" - ", $this->errors);
$this->codelastresult = ($error ? 'KO' : 'OK');
diff --git a/htdocs/emailcollector/class/emailcollectorfilter.class.php b/htdocs/emailcollector/class/emailcollectorfilter.class.php
index d46dfb1c9ae..75a94436ff9 100644
--- a/htdocs/emailcollector/class/emailcollectorfilter.class.php
+++ b/htdocs/emailcollector/class/emailcollectorfilter.class.php
@@ -162,7 +162,7 @@ class EmailCollectorFilter extends CommonObject
if (! in_array($this->type, array('seen','unseen','withtrackingid','withouttrackingid')) && empty($this->rulevalue))
{
$langs->load("errors");
- $this->errors[]=$langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("StringToFilter"));
+ $this->errors[]=$langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("SearchString"));
return -1;
}
diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang
index 08dbd8b4664..1e127a3d063 100644
--- a/htdocs/langs/en_US/admin.lang
+++ b/htdocs/langs/en_US/admin.lang
@@ -1838,6 +1838,7 @@ NothingProcessed=Nothing done
XEmailsDoneYActionsDone=%s emails qualified, %s emails successfully processed (for %s record/actions done) by collector
RecordEvent=Record email event
CreateLeadAndThirdParty=Create lead (and third party if necessary)
+CreateTicketAndThirdParty=Create ticket (and third party if necessary)
CodeLastResult=Result code of last collect
NbOfEmailsInInbox=Number of emails in source directory
LoadThirdPartyFromName=Load third party from name (load only)
@@ -1847,7 +1848,7 @@ WithoutDolTrackingID=Dolibarr Tracking ID not found
FormatZip=Zip
MainMenuCode=Menu entry code (mainmenu)
ECMAutoTree=Show automatic ECM tree
-OperationParamDesc=Define values to use for action, or how to extract values. For example: VALUE:abc REGEX:SUBJECT:([^\s]*) REGEX:BODY:My company name is\s([^\s]*)
+OperationParamDesc=Define values to use for action, or how to extract values. For example: objproperty1=SET:abc objproperty2=EXTRACT:HEADER:X-Myheaderkey.*[^\s]+(.*) objproperty3=EXTRACT:SUBJECT:([^\s]*) objproperty4=EXTRACT:BODY:My company name is\s([^\s]*)
Use a ; char as separator to extract or set several properties.
OpeningHours=Opening hours
OpeningHoursDesc=Enter here the regular opening hours of your company.
ResourceSetup=Configuration of Resource module
@@ -1875,4 +1876,7 @@ WarningValueHigherSlowsDramaticalyOutput=Warning, higher values slows dramatical
DebugBarModuleActivated=Module debugbar is activated and slows dramaticaly the interface
EXPORTS_SHARE_MODELS=Export models are share with everybody
ExportSetup=Setup of module Export
-InstanceUniqueID=Unique ID of the instance
\ No newline at end of file
+InstanceUniqueID=Unique ID of the instance
+SmallerThan=Smaller than
+LargerThan=Larger than
+IfTrackingIDFoundEventWillBeLinked=Note that If a tracking ID is found into incoming email, the event will be automatically linked to the related objects.
\ No newline at end of file
diff --git a/htdocs/langs/en_US/boxes.lang b/htdocs/langs/en_US/boxes.lang
index 41a711f7b5b..b1ab8e41fbc 100644
--- a/htdocs/langs/en_US/boxes.lang
+++ b/htdocs/langs/en_US/boxes.lang
@@ -35,7 +35,7 @@ BoxTitleOldestUnpaidCustomerBills=Customer Invoices: oldest %s unpaid
BoxTitleOldestUnpaidSupplierBills=Vendor Invoices: oldest %s unpaid
BoxTitleCurrentAccounts=Open Accounts: balances
BoxTitleLastModifiedContacts=Contacts/Addresses: last %s modified
-BoxMyLastBookmarks=Bookmarks: last %s
+BoxMyLastBookmarks=Bookmarks: latest %s
BoxOldestExpiredServices=Oldest active expired services
BoxLastExpiredServices=Latest %s oldest contacts with active expired services
BoxTitleLastActionsToDo=Latest %s actions to do
diff --git a/htdocs/ticket/class/ticket.class.php b/htdocs/ticket/class/ticket.class.php
index c603c0489cb..759360a8e84 100644
--- a/htdocs/ticket/class/ticket.class.php
+++ b/htdocs/ticket/class/ticket.class.php
@@ -2365,7 +2365,7 @@ class Ticket extends CommonObject
global $conf;
$defaultref = '';
- $modele = empty($conf->global->TICKETSUP_ADDON) ? 'mod_ticket_simple' : $conf->global->TICKETSUP_ADDON;
+ $modele = empty($conf->global->TICKET_ADDON) ? 'mod_ticket_simple' : $conf->global->TICKET_ADDON;
// Search template files
$file = '';