diff --git a/htdocs/adherents/card.php b/htdocs/adherents/card.php index 9903255e52f..5d57208eb0e 100644 --- a/htdocs/adherents/card.php +++ b/htdocs/adherents/card.php @@ -82,7 +82,7 @@ if (! empty($canvas)) } // Security check -$result=restrictedArea($user, 'adherent', $id, '', '', 'fk_soc', 'rowid', $objcanvas); +$result=restrictedArea($user, 'adherent', $id, '', '', 'socid', 'rowid', $objcanvas); if ($id > 0) { @@ -163,10 +163,10 @@ if (empty($reshook)) $error=0; if (! $error) { - if ($socid != $object->fk_soc) // If link differs from currently in database + if ($socid != $object->socid) // If link differs from currently in database { $sql ="SELECT rowid FROM ".MAIN_DB_PREFIX."adherent"; - $sql.=" WHERE fk_soc = '".$socid."'"; + $sql.=" WHERE socid = '".$socid."'"; $sql.=" AND entity = ".$conf->entity; $resql = $db->query($sql); if ($resql) @@ -492,7 +492,7 @@ if (empty($reshook)) //$object->note = $comment; $object->morphy = $morphy; $object->user_id = $userid; - $object->fk_soc = $socid; + $object->socid = $socid; $object->public = $public; // Fill array 'array_options' with data from add form @@ -1333,10 +1333,10 @@ else if (! empty($conf->societe->enabled)) { print ''.$langs->trans("LinkedToDolibarrThirdParty").''; - if ($object->fk_soc) + if ($object->socid) { $company=new Societe($db); - $result=$company->fetch($object->fk_soc); + $result=$company->fetch($object->socid); print $company->getNomUrl(1); } else @@ -1421,7 +1421,7 @@ else $text=$langs->trans("ConfirmCreateLogin").'
'; if (! empty($conf->societe->enabled)) { - if ($object->fk_soc > 0) $text.=$langs->trans("UserWillBeExternalUser"); + if ($object->socid > 0) $text.=$langs->trans("UserWillBeExternalUser"); else $text.=$langs->trans("UserWillBeInternalUser"); } print $form->formconfirm($_SERVER["PHP_SELF"]."?rowid=".$object->id, $langs->trans("CreateDolibarrLogin"), $text, "confirm_create_user", $formquestion, 'yes'); @@ -1688,17 +1688,17 @@ else print ''; print ''; print ''; print ''; print '
'; - print $form->select_company($object->fk_soc, 'socid', '', 1); + print $form->select_company($object->socid, 'socid', '', 1); print '
'; } else { - if ($object->fk_soc) + if ($object->socid) { $company=new Societe($db); - $result=$company->fetch($object->fk_soc); + $result=$company->fetch($object->socid); print $company->getNomUrl(1); } else @@ -1848,7 +1848,7 @@ else } // Create third party - if (! empty($conf->societe->enabled) && ! $object->fk_soc) + if (! empty($conf->societe->enabled) && ! $object->socid) { if ($user->rights->societe->creer) { diff --git a/htdocs/adherents/class/adherent.class.php b/htdocs/adherents/class/adherent.class.php index 201b6610817..9c32417efb4 100644 --- a/htdocs/adherents/class/adherent.class.php +++ b/htdocs/adherents/class/adherent.class.php @@ -10,6 +10,7 @@ * Copyright (C) 2015-2018 Frédéric France * Copyright (C) 2015 Raphaël Doursenaud * Copyright (C) 2016 Juanjo Menent + * Copyright (C) 2018-2019 Thibault FOUCART * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -557,7 +558,7 @@ class Adherent extends CommonObject $sql.= ", gender = ".($this->gender != -1 ? "'".$this->db->escape($this->gender)."'" : "null"); // 'man' or 'woman' $sql.= ", login = ".($this->login?"'".$this->db->escape($this->login)."'":"null"); $sql.= ", societe = ".($this->societe?"'".$this->db->escape($this->societe)."'":"null"); - $sql.= ", fk_soc = ".($this->fk_soc > 0?$this->db->escape($this->fk_soc):"null"); + $sql.= ", fk_soc = ".($this->socid > 0?$this->db->escape($this->socid):"null"); $sql.= ", address = ".($this->address?"'".$this->db->escape($this->address)."'":"null"); $sql.= ", zip = ".($this->zip?"'".$this->db->escape($this->zip)."'":"null"); $sql.= ", town = ".($this->town?"'".$this->db->escape($this->town)."'":"null"); diff --git a/htdocs/admin/defaultvalues.php b/htdocs/admin/defaultvalues.php index 8e4334c6214..1f0ada4a6f3 100644 --- a/htdocs/admin/defaultvalues.php +++ b/htdocs/admin/defaultvalues.php @@ -251,6 +251,7 @@ print ''; $texthelp=$langs->trans("PageUrlForDefaultValues"); if ($mode == 'createform') $texthelp.=$langs->trans("PageUrlForDefaultValuesCreate", 'societe/card.php', 'societe/card.php?abc=val1&def=val2'); else $texthelp.=$langs->trans("PageUrlForDefaultValuesList", 'societe/list.php', 'societe/list.php?abc=val1&def=val2'); +$texthelp.='

'.$langs->trans("AlsoDefaultValuesAreEffectiveForActionCreate"); $texturl=$form->textwithpicto($langs->trans("Url"), $texthelp); print_liste_field_titre($texturl, $_SERVER["PHP_SELF"], 'page,param', '', $param, '', $sortfield, $sortorder); // Field diff --git a/htdocs/api/class/api.class.php b/htdocs/api/class/api.class.php index df7054ca162..de5a1e75d0a 100644 --- a/htdocs/api/class/api.class.php +++ b/htdocs/api/class/api.class.php @@ -216,7 +216,7 @@ class DolibarrApi * * @param string $resource element to check * @param int $resource_id Object ID if we want to check a particular record (optional) is linked to a owned thirdparty (optional). - * @param type $dbtablename 'TableName&SharedElement' with Tablename is table where object is stored. SharedElement is an optional key to define where to check entity. Not used if objectid is null (optional) + * @param string $dbtablename 'TableName&SharedElement' with Tablename is table where object is stored. SharedElement is an optional key to define where to check entity. Not used if objectid is null (optional) * @param string $feature2 Feature to check, second level of permission (optional). Can be or check with 'level1|level2'. * @param string $dbt_keyfield Field name for socid foreign key if not fk_soc. Not used if objectid is null (optional) * @param string $dbt_select Field name for select if not rowid. Not used if objectid is null (optional) diff --git a/htdocs/api/index.php b/htdocs/api/index.php index 4207618d125..3f47731316c 100644 --- a/htdocs/api/index.php +++ b/htdocs/api/index.php @@ -234,12 +234,13 @@ if (! empty($reg[1]) && ($reg[1] != 'explorer' || ($reg[2] != '/swagger.json' && $classname = ucwords($module); - dol_syslog('Search /' . $moduledirforclass . '/class/api_' . $classfile . '.class.php => dir_part_file=' . $dir_part_file . ' classname=' . $classname); + dol_syslog('Search api file /' . $moduledirforclass . '/class/api_' . $classfile . '.class.php => dir_part_file=' . $dir_part_file . ' classname=' . $classname); $res = false; if ($dir_part_file) $res = include_once $dir_part_file; if (! $res) { + dol_syslog('Failed to make include_once '.$dir_part_file, LOG_WARNING); print 'API not found (failed to include API file)'; header('HTTP/1.1 501 API not found (failed to include API file)'); exit(0); diff --git a/htdocs/bom/class/api_boms.class.php b/htdocs/bom/class/api_boms.class.php index 47e22a3bf62..54f289a5b23 100644 --- a/htdocs/bom/class/api_boms.class.php +++ b/htdocs/bom/class/api_boms.class.php @@ -28,21 +28,13 @@ require_once DOL_DOCUMENT_ROOT.'/bom/class/bom.class.php'; */ /** - * API class for bom bom + * API class for bom * * @access protected * @class DolibarrApiAccess {@requires user,external} */ -class BOMs extends DolibarrApi +class Boms extends DolibarrApi { - /** - * @var array $FIELDS Mandatory fields, checked when create and update object - */ - static $FIELDS = array( - 'label' - ); - - /** * @var BOM $bom {@type BOM} */ @@ -71,16 +63,16 @@ class BOMs extends DolibarrApi */ public function get($id) { - if(! DolibarrApiAccess::$user->rights->bom->read) { + if (! DolibarrApiAccess::$user->rights->bom->read) { throw new RestException(401); } $result = $this->bom->fetch($id); - if( ! $result ) { + if (! $result) { throw new RestException(404, 'BOM not found'); } - if( ! DolibarrApi::_checkAccessToResource('bom', $this->bom->id)) { + if (! DolibarrApi::_checkAccessToResource('bom', $this->bom->id, 'bom_bom')) { throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } @@ -107,33 +99,33 @@ class BOMs extends DolibarrApi global $db, $conf; $obj_ret = array(); - + $tmpobject = new BOM($db); + $socid = DolibarrApiAccess::$user->societe_id ? DolibarrApiAccess::$user->societe_id : ''; - $restictonsocid = 0; // Set to 1 if there is a field socid in table of object + $restrictonsocid = 0; // Set to 1 if there is a field socid in table of object // If the internal user must only see his customers, force searching by him $search_sale = 0; - if ($restictonsocid && ! DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) $search_sale = DolibarrApiAccess::$user->id; + if ($restrictonsocid && ! DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) $search_sale = DolibarrApiAccess::$user->id; $sql = "SELECT t.rowid"; - if ($restictonsocid && (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) $sql .= ", sc.fk_soc, sc.fk_user"; // We need these fields in order to filter by sale (including the case where the user can only see his prospects) - $sql.= " FROM ".MAIN_DB_PREFIX."bom_mytable as t"; + if ($restrictonsocid && (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) $sql .= ", sc.fk_soc, sc.fk_user"; // We need these fields in order to filter by sale (including the case where the user can only see his prospects) + $sql.= " FROM ".MAIN_DB_PREFIX.$tmpobject->table_element." as t"; - if ($restictonsocid && (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale + if ($restrictonsocid && (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale $sql.= " WHERE 1 = 1"; // Example of use $mode //if ($mode == 1) $sql.= " AND s.client IN (1, 3)"; //if ($mode == 2) $sql.= " AND s.client IN (2, 3)"; - $tmpobject = new BOM($db); if ($tmpobject->ismultientitymanaged) $sql.= ' AND t.entity IN ('.getEntity('bom').')'; - if ($restictonsocid && (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) $sql.= " AND t.fk_soc = sc.fk_soc"; - if ($restictonsocid && $socid) $sql.= " AND t.fk_soc = ".$socid; - if ($restictonsocid && $search_sale > 0) $sql.= " AND t.rowid = sc.fk_soc"; // Join for the needed table to filter by sale + if ($restrictonsocid && (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) $sql.= " AND t.fk_soc = sc.fk_soc"; + if ($restrictonsocid && $socid) $sql.= " AND t.fk_soc = ".$socid; + if ($restrictonsocid && $search_sale > 0) $sql.= " AND t.rowid = sc.fk_soc"; // Join for the needed table to filter by sale // Insert sale filter - if ($restictonsocid && $search_sale > 0) + if ($restrictonsocid && $search_sale > 0) { $sql .= " AND sc.fk_user = ".$search_sale; } @@ -190,7 +182,7 @@ class BOMs extends DolibarrApi */ public function post($request_data = null) { - if(! DolibarrApiAccess::$user->rights->bom->create) { + if(! DolibarrApiAccess::$user->rights->bom->write) { throw new RestException(401); } // Check mandatory fields @@ -215,7 +207,7 @@ class BOMs extends DolibarrApi */ public function put($id, $request_data = null) { - if(! DolibarrApiAccess::$user->rights->bom->create) { + if(! DolibarrApiAccess::$user->rights->bom->write) { throw new RestException(401); } @@ -224,7 +216,7 @@ class BOMs extends DolibarrApi throw new RestException(404, 'BOM not found'); } - if( ! DolibarrApi::_checkAccessToResource('bom', $this->bom->id)) { + if( ! DolibarrApi::_checkAccessToResource('bom', $this->bom->id, 'bom_bom')) { throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } @@ -239,7 +231,7 @@ class BOMs extends DolibarrApi } else { - throw new RestException(500, $this->commande->error); + throw new RestException(500, $this->bom->error); } } @@ -259,7 +251,7 @@ class BOMs extends DolibarrApi throw new RestException(404, 'BOM not found'); } - if (! DolibarrApi::_checkAccessToResource('bom', $this->bom->id)) { + if (! DolibarrApi::_checkAccessToResource('bom', $this->bom->id, 'bom_bom')) { throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } @@ -309,12 +301,13 @@ class BOMs extends DolibarrApi */ private function _validate($data) { - $bom = array(); - foreach (BOMs::$FIELDS as $field) { + $myobject = array(); + foreach ($this->myobject->fields as $field => $propfield) { + if (in_array($field, array('rowid', 'entity', 'date_creation', 'tms', 'fk_user_creat')) || $propfield['notnull'] != 1) continue; // Not a mandatory field if (!isset($data[$field])) throw new RestException(400, "$field field missing"); - $bom[$field] = $data[$field]; + $myobject[$field] = $data[$field]; } - return $bom; + return $myobject; } } diff --git a/htdocs/comm/action/class/actioncomm.class.php b/htdocs/comm/action/class/actioncomm.class.php index b543d6790c6..ebe4e48f264 100644 --- a/htdocs/comm/action/class/actioncomm.class.php +++ b/htdocs/comm/action/class/actioncomm.class.php @@ -281,6 +281,7 @@ class ActionComm extends CommonObject if (! empty($this->datep) && ! empty($this->datef) && $this->datep > $this->datef) $this->datef=$this->datep; //if (! empty($this->date) && ! empty($this->dateend) && $this->date > $this->dateend) $this->dateend=$this->date; if (! isset($this->fk_project) || $this->fk_project < 0) $this->fk_project = 0; + // For backward compatibility if ($this->elementtype=='facture') $this->elementtype='invoice'; if ($this->elementtype=='commande') $this->elementtype='order'; if ($this->elementtype=='contrat') $this->elementtype='contract'; diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 454936d2998..fae9ab49cc8 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -6525,7 +6525,7 @@ abstract class CommonObject $out .= $extrafields->showOutputField($key, $value); break; case "edit": - $out .= $extrafields->showInputField($key, $value, '', $keysuffix, '', 0, $this->id); + $out .= $extrafields->showInputField($key, $value, '', $keysuffix, '', 0, $this->id, $this->table_element); break; } diff --git a/htdocs/core/class/extrafields.class.php b/htdocs/core/class/extrafields.class.php index 26acdf50fcc..caea57280b9 100644 --- a/htdocs/core/class/extrafields.class.php +++ b/htdocs/core/class/extrafields.class.php @@ -1567,6 +1567,9 @@ class ExtraFields if ($type == 'date') $out.=' (YYYY-MM-DD)'; elseif ($type == 'datetime') $out.=' (YYYY-MM-DD HH:MM:SS)'; */ + if (! empty($help)) { + $out .= $form->textwithpicto("", $help); + } return $out; } diff --git a/htdocs/core/class/html.formticket.class.php b/htdocs/core/class/html.formticket.class.php index 59996942cd3..1d681d2672b 100644 --- a/htdocs/core/class/html.formticket.class.php +++ b/htdocs/core/class/html.formticket.class.php @@ -834,7 +834,7 @@ class FormTicket if ($user->rights->ticket->write && !$user->socid) { print ''; - $checkbox_selected = ( GETPOST('send_email') == "1" ? ' checked' : ''); + $checkbox_selected = (GETPOST('send_email') == "1" ? ' checked' : ''); print ' '; print ''; print ''; @@ -852,20 +852,10 @@ class FormTicket print ''; } - // Substitution array - if ($this->withsubstit) { - print ''; - $help=""; - foreach ($this->substit as $key => $val) { - $help.=$key.' -> '.$langs->trans($val).'
'; - } - print $form->textwithpicto($langs->trans("TicketMessageSubstitutionReplacedByGenericValues"), $help); - print ""; - } - + // Private message (not visible by customer/external user) if (! $user->socid) { print ''; - $checkbox_selected = ( GETPOST('private_message') == "1" ? ' checked' : ''); + $checkbox_selected = (GETPOST('private_message', 'alpha') == "1" ? ' checked' : ''); print ' '; print ''; print ''; @@ -873,8 +863,7 @@ class FormTicket print ''; } - - print '' . $langs->trans('Subject') . ''; + print '' . $langs->trans('Subject') . ''; $label_title = empty($conf->global->MAIN_APPLICATION_TITLE) ? $mysoc->name : $conf->global->MAIN_APPLICATION_TITLE; print ''; print ''; diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 4c0b15c8d46..3f5480ee455 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -307,7 +307,7 @@ function GETPOST($paramname, $check = 'none', $method = 0, $filter = null, $opti } if (! empty($conf->global->MAIN_ENABLE_DEFAULT_VALUES)) { - if (! empty($_GET['action']) && $_GET['action'] == 'create' && ! isset($_GET[$paramname]) && ! isset($_POST[$paramname])) + if (! empty($_GET['action']) && preg_match('/^create/', $_GET['action']) && ! isset($_GET[$paramname]) && ! isset($_POST[$paramname])) { // Now search in setup to overwrite default values if (! empty($user->default_values)) // $user->default_values defined from menu 'Setup - Default values' @@ -1299,6 +1299,7 @@ function dol_banner_tab($object, $paramid, $morehtml = '', $shownav = 1, $fieldi if ($object->element == 'member') $modulepart='memberphoto'; if ($object->element == 'user') $modulepart='userphoto'; if ($object->element == 'product') $modulepart='product'; + if ($object->element == 'ticket') $modulepart='ticket'; if (class_exists("Imagick")) { diff --git a/htdocs/core/lib/functions2.lib.php b/htdocs/core/lib/functions2.lib.php index 16fb210ee4d..e5c765383af 100644 --- a/htdocs/core/lib/functions2.lib.php +++ b/htdocs/core/lib/functions2.lib.php @@ -2436,6 +2436,9 @@ function getModuleDirForApiClass($module) elseif ($module == 'tickets') { $moduledirforclass = 'ticket'; } + elseif ($module == 'boms') { + $moduledirforclass = 'bom'; + } return $moduledirforclass; } diff --git a/htdocs/core/modules/modService.class.php b/htdocs/core/modules/modService.class.php index 022e0c74a54..9db733e4bb2 100644 --- a/htdocs/core/modules/modService.class.php +++ b/htdocs/core/modules/modService.class.php @@ -164,7 +164,7 @@ class modService extends DolibarrModules if (! empty($conf->barcode->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r], array('p.barcode'=>'product')); if (! empty($conf->fournisseur->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r], array('s.nom'=>'product_supplier_ref','pf.ref_fourn'=>'product_supplier_ref','pf.unitprice'=>'product_supplier_ref','pf.quantity'=>'product_supplier_ref','pf.remise_percent'=>'product_supplier_ref','pf.delivery_time_days'=>'product_supplier_ref')); if (! empty($conf->global->MAIN_MULTILANGS)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r], array('l.lang'=>'translation', 'l.label'=>'translation','l.description'=>'translation','l.note'=>'translation')); - if (! empty($conf->global->EXPORTTOOL_CATEGORIES)) $this->export_dependencies_array[$r]= array('category'=>'p.rowid'); + if (! empty($conf->global->EXPORTTOOL_CATEGORIES)) $this->export_dependencies_array[$r]=array('category'=>'p.rowid'); if (! empty($conf->stock->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r], array('p.stock'=>'product','p.pmp'=>'product')); if (! empty($conf->barcode->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r], array('p.barcode'=>'product')); if (! empty($conf->fournisseur->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r], array('s.nom'=>'product_supplier_ref','pf.ref_fourn'=>'product_supplier_ref','pf.unitprice'=>'product_supplier_ref','pf.quantity'=>'product_supplier_ref','pf.remise_percent'=>'product_supplier_ref','pf.delivery_time_days'=>'product_supplier_ref')); diff --git a/htdocs/core/tpl/objectline_create.tpl.php b/htdocs/core/tpl/objectline_create.tpl.php index df8301f4104..4a4febe65d3 100644 --- a/htdocs/core/tpl/objectline_create.tpl.php +++ b/htdocs/core/tpl/objectline_create.tpl.php @@ -162,13 +162,13 @@ if ($nolinesbefore) { ?> global->MAIN_VIEW_LINE_NUMBER)) { - $coldisplay++; - echo ''; -} + // Adds a line numbering column + if (! empty($conf->global->MAIN_VIEW_LINE_NUMBER)) { + $coldisplay++; + echo ''; + } $coldisplay++; ?> diff --git a/htdocs/install/mysql/migration/9.0.0-10.0.0.sql b/htdocs/install/mysql/migration/9.0.0-10.0.0.sql index 9aa395c22d6..e5b925b0d83 100644 --- a/htdocs/install/mysql/migration/9.0.0-10.0.0.sql +++ b/htdocs/install/mysql/migration/9.0.0-10.0.0.sql @@ -94,6 +94,9 @@ ALTER TABLE llx_bank_url DROP INDEX uk_bank_url; ALTER TABLE llx_bank_url ADD UNIQUE INDEX uk_bank_url (fk_bank, url_id, type); ALTER TABLE llx_actioncomm ADD COLUMN calling_duration integer; +ALTER TABLE llx_actioncomm ADD COLUMN visibility varchar(12) DEFAULT 'default'; + +DROP TABLE llx_ticket_msg; ALTER TABLE llx_don ADD COLUMN fk_soc integer NULL; diff --git a/htdocs/install/mysql/tables/llx_actioncomm.sql b/htdocs/install/mysql/tables/llx_actioncomm.sql index 046b8c155bd..ad6ea20115c 100644 --- a/htdocs/install/mysql/tables/llx_actioncomm.sql +++ b/htdocs/install/mysql/tables/llx_actioncomm.sql @@ -46,7 +46,8 @@ create table llx_actioncomm transparency integer, -- transparency (ical standard). used to say if user assigned to event are busy or not by event. This field may be deprecated if we want to store transparency for each assigned user, moved into table llx_actioncomm_resources. priority smallint, -- priority (ical standard) - fulldayevent smallint NOT NULL default 0, -- priority (ical standard) + visibility varchar(12) DEFAULT 'default', -- visibility (ical standard) - 'default', 'public', 'private', 'confidential' + fulldayevent smallint NOT NULL default 0, -- full day (ical standard) punctual smallint NOT NULL default 1, -- deprecated. milestone is event with date start (datep) = date end (datep2) percent smallint NOT NULL default 0, location varchar(128), diff --git a/htdocs/install/mysql/tables/llx_ticket_msg.key.sql b/htdocs/install/mysql/tables/llx_ticket_msg.key.sql deleted file mode 100755 index f6ff6fc5e88..00000000000 --- a/htdocs/install/mysql/tables/llx_ticket_msg.key.sql +++ /dev/null @@ -1,17 +0,0 @@ --- SQL definition for module ticket --- Copyright (C) 2013 Jean-François FERRY --- --- This program is free software: you can redistribute it and/or modify --- it under the terms of the GNU General Public License as published by --- the Free Software Foundation, either version 3 of the License, or --- (at your option) any later version. --- --- This program is distributed in the hope that it will be useful, --- but WITHOUT ANY WARRANTY; without even the implied warranty of --- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --- GNU General Public License for more details. --- --- You should have received a copy of the GNU General Public License --- along with this program. If not, see . - ---ALTER TABLE llx_ticket_msg ADD CONSTRAINT fk_ticket_msg_fk_track_id FOREIGN KEY (fk_track_id) REFERENCES llx_ticket (track_id); diff --git a/htdocs/install/mysql/tables/llx_ticket_msg.sql b/htdocs/install/mysql/tables/llx_ticket_msg.sql deleted file mode 100755 index 7ff3297b0cc..00000000000 --- a/htdocs/install/mysql/tables/llx_ticket_msg.sql +++ /dev/null @@ -1,26 +0,0 @@ --- SQL definition for module ticket --- Copyright (C) 2013 Jean-François FERRY --- --- This program is free software: you can redistribute it and/or modify --- it under the terms of the GNU General Public License as published by --- the Free Software Foundation, either version 3 of the License, or --- (at your option) any later version. --- --- This program is distributed in the hope that it will be useful, --- but WITHOUT ANY WARRANTY; without even the implied warranty of --- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --- GNU General Public License for more details. --- --- You should have received a copy of the GNU General Public License --- along with this program. If not, see . - -CREATE TABLE llx_ticket_msg -( - rowid integer AUTO_INCREMENT PRIMARY KEY, - entity integer DEFAULT 1, - fk_track_id varchar(128), - fk_user_action integer, - datec datetime, - message text, - private integer DEFAULT 0 -)ENGINE=innodb; diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 90abbe90fc6..daba22fe660 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -470,6 +470,7 @@ TheKeyIsTheNameOfHtmlField=This is the name of the HTML field. Technical knowled PageUrlForDefaultValues=You must enter the relative path of the page URL. If you include parameters in URL, the default values will be effective if all parameters are set to same value. PageUrlForDefaultValuesCreate=
Example:
For the form to create a new third party, it is %s.
For URL of external modules installed into custom directory, do not include the "custom/", so use path like mymodule/mypage.php and not custom/mymodule/mypage.php.
If you want default value only if url has some parameter, you can use %s PageUrlForDefaultValuesList=
Example:
For the page that lists third parties, it is %s.
For URL of external modules installed into custom directory, do not include the "custom/" so use a path like mymodule/mypagelist.php and not custom/mymodule/mypagelist.php.
If you want default value only if url has some parameter, you can use %s +AlsoDefaultValuesAreEffectiveForActionCreate=Also note that overwritting default values for form creation works only for pages that were correctly designed (so with parameter action=create...) EnableDefaultValues=Enable customization of default values EnableOverwriteTranslation=Enable usage of overwritten translation GoIntoTranslationMenuToChangeThis=A translation has been found for the key with this code. To change this value, you must edit it from Home-Setup-translation. diff --git a/htdocs/langs/en_US/main.lang b/htdocs/langs/en_US/main.lang index 3aec931714b..463cf828b29 100644 --- a/htdocs/langs/en_US/main.lang +++ b/htdocs/langs/en_US/main.lang @@ -855,7 +855,7 @@ Download=Download DownloadDocument=Download document ActualizeCurrency=Update currency rate Fiscalyear=Fiscal year -ModuleBuilder=Module Builder +ModuleBuilder=Module and Application Builder SetMultiCurrencyCode=Set currency BulkActions=Bulk actions ClickToShowHelp=Click to show tooltip help diff --git a/htdocs/langs/en_US/modulebuilder.lang b/htdocs/langs/en_US/modulebuilder.lang index 8e2d57a03fc..5cb927dc8b7 100644 --- a/htdocs/langs/en_US/modulebuilder.lang +++ b/htdocs/langs/en_US/modulebuilder.lang @@ -1,5 +1,5 @@ # Dolibarr language file - Source file is en_US - loan -ModuleBuilderDesc=This tool must be used only by experienced users or developers. It provides utilities to build or edit your own module.
Documentation for alternative manual development is here. +ModuleBuilderDesc=This tool must be used only by experienced users or developers. It provides utilities to build or edit your own module. Documentation for alternative manual development is here. EnterNameOfModuleDesc=Enter name of the module/application to create with no spaces. Use uppercase to separate words (For example: MyModule, EcommerceForShop, SyncWithMySystem...) EnterNameOfObjectDesc=Enter name of the object to create with no spaces. Use uppercase to separate words (For example: MyObject, Student, Teacher...). The CRUD class file, but also API file, pages to list/add/edit/delete object and SQL files will be generated. ModuleBuilderDesc2=Path where modules are generated/edited (first directory for external modules defined into %s): %s @@ -21,13 +21,14 @@ ModuleBuilderDesctriggers=This is the view of triggers provided by your module. ModuleBuilderDeschooks=This tab is dedicated to hooks. ModuleBuilderDescwidgets=This tab is dedicated to manage/build widgets. ModuleBuilderDescbuildpackage=You can generate here a "ready to distribute" package file (a normalized .zip file) of your module and a "ready to distribute" documentation file. Just click on button to build the package or documentation file. -EnterNameOfModuleToDeleteDesc=You can delete your module. WARNING: ALL files of module AND structured data and documentation will be deleted! -EnterNameOfObjectToDeleteDesc=You can delete an object. WARNING: All files related to object will be deleted! +EnterNameOfModuleToDeleteDesc=You can delete your module. WARNING: All coding files of module (generated or created manually) AND structured data and documentation will be deleted! +EnterNameOfObjectToDeleteDesc=You can delete an object. WARNING: All coding files (generated or created manually) related to object will be deleted! DangerZone=Danger zone BuildPackage=Build package +BuildPackageDesc=You can generate a zip package or your application so your are ready to distribute it on any Dolibarr. You can also distribute it or sell it on marketplace like DoliStore.com. BuildDocumentation=Build documentation ModuleIsNotActive=This module is not activated yet. Go to %s to make it live or click here: -ModuleIsLive=This module has been activated. Any change on it may break a current active feature. +ModuleIsLive=This module has been activated. Any change may break a current live feature. DescriptionLong=Long description EditorName=Name of editor EditorUrl=URL of editor @@ -43,10 +44,11 @@ PathToModulePackage=Path to zip of module/application package PathToModuleDocumentation=Path to file of module/application documentation (%s) SpaceOrSpecialCharAreNotAllowed=Spaces or special characters are not allowed. FileNotYetGenerated=File not yet generated -RegenerateClassAndSql=Erase and regenerate class and sql files +RegenerateClassAndSql=Force update of .class and .sql files RegenerateMissingFiles=Generate missing files SpecificationFile=File of documentation LanguageFile=File for language +ObjectProperties=Object Properties ConfirmDeleteProperty=Are you sure you want to delete the property %s? This will change code in PHP class but also remove column from table definition of object. NotNull=Not NULL NotNullDesc=1=Set database to NOT NULL. -1=Allow null values and force value to NULL if empty ('' or 0). @@ -62,7 +64,8 @@ ReadmeFile=Readme file ChangeLog=ChangeLog file TestClassFile=File for PHP Unit Test class SqlFile=Sql file -PageForLib=File for PHP libraries +PageForLib=File for PHP library +PageForObjLib=File for PHP library dedicated to object SqlFileExtraFields=Sql file for complementary attributes SqlFileKey=Sql file for keys AnObjectAlreadyExistWithThisNameAndDiffCase=An object already exists with this name and a different case @@ -81,8 +84,10 @@ IsAMeasureDesc=Can the value of field be cumulated to get a total into list? (Ex SearchAllDesc=Is the field used to make a search from the quick search tool? (Examples: 1 or 0) SpecDefDesc=Enter here all documentation you want to provide with your module that is not already defined by other tabs. You can use .md or better, the rich .asciidoc syntax. LanguageDefDesc=Enter in this files, all the key and the translation for each language file. -MenusDefDesc=Define here the menus provided by your module (once defined, they are visible into the menu editor %s) -PermissionsDefDesc=Define here the new permissions provided by your module (once defined, they are visible into the default permissions setup %s) +MenusDefDesc=Define here the menus provided by your module +PermissionsDefDesc=Define here the new permissions provided by your module +MenusDefDescTooltip=The menus provided by your module/application are defined into the array $this->menus into the module descriptor file. You can edit manually this file or use the embedded editor.

Note: Once defined (and module re-activated), menus are also visible into the menu editor available to administrator users on %s. +PermissionsDefDescTooltip=The permissions provided by your module/application are defined into the array $this->rights into the module descriptor file. You can edit manually this file or use the embedded editor.

Note: Once defined (and module re-activated), permissions are visible into the default permissions setup %s. HooksDefDesc=Define in the module_parts['hooks'] property, in the module descriptor, the context of hooks you want to manage (list of contexts can be found by a search on 'initHooks(' in core code).
Edit the hook file to add code of your hooked functions (hookable functions can be found by a search on 'executeHooks' in core code). TriggerDefDesc=Define in the trigger file the code you want to execute for each business event executed. SeeIDsInUse=See IDs in use in your installation @@ -109,4 +114,5 @@ UseSpecificEditorName = Use a specific editor name UseSpecificEditorURL = Use a specific editor URL UseSpecificFamily = Use a specific family UseSpecificAuthor = Use a specific author -UseSpecificVersion = Use a specific initial version \ No newline at end of file +UseSpecificVersion = Use a specific initial version +ModuleMustBeEnabled=The module/application must be enabled first \ No newline at end of file diff --git a/htdocs/langs/en_US/ticket.lang b/htdocs/langs/en_US/ticket.lang index 8265df1b370..c84dc17f087 100644 --- a/htdocs/langs/en_US/ticket.lang +++ b/htdocs/langs/en_US/ticket.lang @@ -58,9 +58,10 @@ Notify_TICKET_SENTBYMAIL=Send ticket message by email # Status NotRead=Not read Read=Read -Answered=Answered Assigned=Assigned InProgress=In progress +NeedMoreInformation=Waiting more information +Answered=Answered Waiting=Waiting Closed=Closed Deleted=Deleted diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php index 0e80c0ba4ac..0ad297221be 100644 --- a/htdocs/modulebuilder/index.php +++ b/htdocs/modulebuilder/index.php @@ -156,8 +156,7 @@ if ($dirins && $action == 'initmodule' && $modulename) dol_delete_file($destdir.'/scripts/'.strtolower($modulename).'.php'); dol_delete_dir($destdir.'/scripts'); - - // Delete some files related to Object (because the dolCopyDir has copied everything) + // Delete some files related to Object (because the previous dolCopyDir has copied everything) dol_delete_file($destdir.'/myobject_card.php'); dol_delete_file($destdir.'/myobject_note.php'); dol_delete_file($destdir.'/myobject_document.php'); @@ -222,6 +221,39 @@ if ($dirins && $action == 'initmodule' && $modulename) } } +if ($dirins && $action == 'initapi' && !empty($module)) +{ + dol_mkdir($dirins.'/'.strtolower($module).'/class'); + $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template'; + $srcfile = $srcdir.'/class/api_mymodule.class.php'; + $destfile = $dirins.'/'.strtolower($module).'/class/api_'.strtolower($module).'.class.php'; + //var_dump($srcfile);var_dump($destfile); + $result = dol_copy($srcfile, $destfile, 0, 0); + + if ($result > 0) + { + $modulename = ucfirst($module); // Force first letter in uppercase + $objectname = $tabobj; + + //var_dump($phpfileval['fullname']); + $arrayreplacement=array( + 'mymodule'=>strtolower($modulename), + 'MyModule'=>$modulename, + 'MYMODULE'=>strtoupper($modulename), + 'My module'=>$modulename, + 'my module'=>$modulename, + 'Mon module'=>$modulename, + 'mon module'=>$modulename, + 'htdocs/modulebuilder/template'=>strtolower($modulename), + 'myobject'=>strtolower($objectname), + 'MyObject'=>$objectname, + 'MYOBJECT'=>strtoupper($objectname), + '---Put here your own copyright and developer email---'=>dol_print_date($now, '%Y').' '.$user->getFullName($langs).($user->email?' <'.$user->email.'>':'') + ); + + dolReplaceInFile($destfile, $arrayreplacement); + } +} if ($dirins && $action == 'inithook' && !empty($module)) { dol_mkdir($dirins.'/'.strtolower($module).'/class'); @@ -230,6 +262,26 @@ if ($dirins && $action == 'inithook' && !empty($module)) $destfile = $dirins.'/'.strtolower($module).'/class/actions_'.strtolower($module).'.class.php'; //var_dump($srcfile);var_dump($destfile); $result = dol_copy($srcfile, $destfile, 0, 0); + + if ($result > 0) + { + $modulename = ucfirst($module); // Force first letter in uppercase + + //var_dump($phpfileval['fullname']); + $arrayreplacement=array( + 'mymodule'=>strtolower($modulename), + 'MyModule'=>$modulename, + 'MYMODULE'=>strtoupper($modulename), + 'My module'=>$modulename, + 'my module'=>$modulename, + 'Mon module'=>$modulename, + 'mon module'=>$modulename, + 'htdocs/modulebuilder/template'=>strtolower($modulename), + '---Put here your own copyright and developer email---'=>dol_print_date($now, '%Y').' '.$user->getFullName($langs).($user->email?' <'.$user->email.'>':'') + ); + + dolReplaceInFile($destfile, $arrayreplacement); + } } if ($dirins && $action == 'inittrigger' && !empty($module)) { @@ -500,10 +552,10 @@ if ($dirins && $action == 'initobject' && $module && $objectname) 'sql/llx_mymodule_myobject.sql'=>'sql/llx_'.strtolower($module).'_'.strtolower($objectname).'.sql', 'sql/llx_mymodule_myobject_extrafields.sql'=>'sql/llx_'.strtolower($module).'_'.strtolower($objectname).'_extrafields.sql', 'sql/llx_mymodule_myobject.key.sql'=>'sql/llx_'.strtolower($module).'_'.strtolower($objectname).'.key.sql', - 'scripts/myobject.php'=>'scripts/'.strtolower($objectname).'.php', + //'scripts/mymodule.php'=>'scripts/'.strtolower($objectname).'.php', 'img/object_myobject.png'=>'img/object_'.strtolower($objectname).'.png', 'class/myobject.class.php'=>'class/'.strtolower($objectname).'.class.php', - 'class/api_mymodule.class.php'=>'class/api_'.strtolower($module).'.class.php' + //'class/api_mymodule.class.php'=>'class/api_'.strtolower($module).'.class.php' ); foreach($filetogenerate as $srcfile => $destfile) @@ -524,8 +576,8 @@ if ($dirins && $action == 'initobject' && $module && $objectname) } } - if (! $error) - { + //if (! $error) // If there is error copying 1 file, we still have to make the replacement + //{ // Scan for object class files $listofobject = dol_dir_list($destdir.'/class', 'files', 0, '\.class\.php$'); @@ -536,6 +588,7 @@ if ($dirins && $action == 'initobject' && $module && $objectname) if (preg_match('/^actions_/', $fileobj['name'])) continue; $tmpcontent=file_get_contents($fileobj['fullname']); + $reg=array(); if (preg_match('/class\s+([^\s]*)\s+extends\s+CommonObject/ims', $tmpcontent, $reg)) { $objectnameloop = $reg[1]; @@ -587,7 +640,7 @@ if ($dirins && $action == 'initobject' && $module && $objectname) // TODO } - } + //} } if (! $error) @@ -730,11 +783,11 @@ if ($dirins && $action == 'addproperty' && !empty($module) && ! empty($tabobj)) } } - if (GETPOST('regeneratemissing')) + /*if (GETPOST('regeneratemissing')) { setEventMessages($langs->trans("FeatureNotYetAvailable"), null, 'warnings'); $error++; - } + }*/ // Edit the class file to write properties if (! $error) @@ -760,7 +813,7 @@ if ($dirins && $action == 'addproperty' && !empty($module) && ! empty($tabobj)) clearstatcache(true); // Make a redirect to reload all data - header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=objects&module='.$module.'&tabobj='.$objectname.'&nocache='.time()); + header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=objects&module='.$module.($forceddirread?'@'.$dirread:'').'&tabobj='.$objectname.'&nocache='.time()); exit; } @@ -795,7 +848,7 @@ if ($dirins && $action == 'confirm_deleteproperty' && $propertykey) clearstatcache(true); // Make a redirect to reload all data - header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=objects&module='.$module.'&tabobj='.$objectname); + header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=objects&module='.$module.($forceddirread?'@'.$dirread:'').'&tabobj='.$objectname); exit; } @@ -1030,9 +1083,9 @@ if ($action == 'savefile' && empty($cancel)) if ($action == 'set' && $user->admin) { $param=''; - if ($module) $param.='&module='.$module; - if ($tab) $param.='&tab='.$tab; - if ($tabobj) $param.='&tabobj='.$tabobj; + if ($module) $param.='&module='.urlencode($module); + if ($tab) $param.='&tab='.urlencode($tab); + if ($tabobj) $param.='&tabobj='.urlencode($tabobj); $value = GETPOST('value', 'alpha'); $resarray = activateModule($value); @@ -1065,9 +1118,9 @@ if ($action == 'set' && $user->admin) if ($action == 'reset' && $user->admin) { $param=''; - if ($module) $param.='&module='.$module; - if ($tab) $param.='&tab='.$tab; - if ($tabobj) $param.='&tabobj='.$tabobj; + if ($module) $param.='&module='.urlencode($module); + if ($tab) $param.='&tab='.urlencode($tab); + if ($tabobj) $param.='&tabobj='.urlencode($tabobj); $value = GETPOST('value', 'alpha'); $result=unActivateModule($value); @@ -1105,7 +1158,7 @@ $text=$langs->trans("ModuleBuilder"); print load_fiche_titre($text, '', 'title_setup'); -print $langs->trans("ModuleBuilderDesc", 'https://wiki.dolibarr.org/index.php/Module_development#Create_your_module').'
'; +print ''.$langs->trans("ModuleBuilderDesc", 'https://wiki.dolibarr.org/index.php/Module_development#Create_your_module').'
'; $dirsrootforscan=array($dirread); if ($dirread != DOL_DOCUMENT_ROOT && $conf->global->MAIN_FEATURES_LEVEL >=2) { $dirsrootforscan[]=DOL_DOCUMENT_ROOT; } @@ -1310,9 +1363,9 @@ elseif (! empty($module)) $const_name = 'MAIN_MODULE_'.strtoupper($module); $param=''; - if ($tab) $param.= '&tab='.$tab; - if ($module) $param.='&module='.$module; - if ($tabobj) $param.='&tabobj='.$tabobj; + if ($tab) $param.='&tab='.urlencode($tab); + if ($module) $param.='&module='.urlencode($module); + if ($tabobj) $param.='&tabobj='.urlencode($tabobj); $urltomodulesetup=''.$langs->trans('Home').'-'.$langs->trans("Setup").'-'.$langs->trans("Modules").''; $linktoenabledisable=''; @@ -1595,8 +1648,8 @@ elseif (! empty($module)) { $pathtofile = $modulelowercase.'/langs/'.$langfile['relativename']; print ' '.$langs->trans("LanguageFile").' '.basename(dirname($pathtofile)).' : '.$pathtofile.''; - print ''.img_picto($langs->trans("Edit"), 'edit').''; - print ''.img_picto($langs->trans("Delete"), 'delete').''; + print ''.img_picto($langs->trans("Edit"), 'edit').''; + print ''.img_picto($langs->trans("Delete"), 'delete').''; print ''; } print ''; @@ -1698,7 +1751,7 @@ elseif (! empty($module)) print '
'; print '
'; print '
'; - print $langs->trans("Or"); + print $langs->trans("or"); print '
'; print '
'; print '
'; @@ -1782,8 +1835,26 @@ elseif (! empty($module)) print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; print ' '.$langs->trans("ApiClassFile").' : '.($realpathtoapi?'':'').$pathtoapi.($realpathtoapi?'':'').''; - print ' '.img_picto($langs->trans("Edit"), 'edit').''; - print '   '.$langs->trans("GoToApiExplorer").''; + if ($realpathtoapi) + { + print ' '.img_picto($langs->trans("Edit"), 'edit').''; + print '   '; + print ''.img_picto($langs->trans("Delete"), 'delete').''; + print '   '; + if (empty($conf->global->$const_name)) // If module is not activated + { + print ''.$langs->trans("GoToApiExplorer").''; + } + else + { + print ''.$langs->trans("GoToApiExplorer").''; + } + } + else + { + //print ''.$langs->trans("FileNotYetGenerated").' '; + print ''; + } print '
'; print ' '.$langs->trans("TestClassFile").' : '.($realpathtophpunit?'':'').$pathtophpunit.($realpathtophpunit?'':'').''; print ' '.img_picto($langs->trans("Edit"), 'edit').''; @@ -1824,7 +1895,7 @@ elseif (! empty($module)) $urlofcard = dol_buildpath($pathtocard, 1); print '
'; - print ' '.$langs->trans("PageForList").' : '.($realpathtosql?'':'').$pathtolist.($realpathtosql?'':'').''; + print ' '.$langs->trans("PageForList").' : '.($realpathtolist?'':'').$pathtolist.($realpathtolist?'':'').''; print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; print ' '.$langs->trans("PageForCreateEditView").' : '.($realpathtocard?'':'').$pathtocard.($realpathtocard?'':'').'?action=create'; @@ -1840,10 +1911,11 @@ elseif (! empty($module)) print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; + /* This is already on Tab CLI print '
'; print ' '.$langs->trans("ScriptFile").' : '.($realpathtoscript?'':'').$pathtoscript.($realpathtoscript?'':'').''; print ' '.img_picto($langs->trans("Edit"), 'edit').''; - print '
'; + print '
';*/ print '
'; @@ -1888,10 +1960,10 @@ elseif (! empty($module)) print ''; print ''; - print ''; + //print ''; print '

'; - print load_fiche_titre($langs->trans("Properties"), '', ''); + print load_fiche_titre($langs->trans("ObjectProperties"), '', ''); print '
'; @@ -2040,7 +2112,7 @@ elseif (! empty($module)) $format='asciidoc'; if (preg_match('/\.md$/i', $spec['name'])) $format='markdown'; print ' '.$langs->trans("SpecificationFile").' : '.$pathtofile.''; - print ' '.img_picto($langs->trans("Edit"), 'edit').''; + print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; } } @@ -2137,17 +2209,22 @@ elseif (! empty($module)) if ($action != 'editfile' || empty($file)) { - print ''.$langs->trans("MenusDefDesc", ''.$langs->trans('Menus').'').'
'; + print ''; + $htmlhelp=$langs->trans("MenusDefDescTooltip", ''.$langs->trans('Setup').' - '.$langs->trans('Menus').''); + print $form->textwithpicto($langs->trans("MenusDefDesc"), $htmlhelp, 1, 'help', '', 0, 2, 'helpondesc').'
'; + print '
'; print '
'; print ' '.$langs->trans("DescriptorFile").' : '.$pathtofile.''; - print ' '.img_picto($langs->trans("Edit"), 'edit').''; + print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; print '
'; print load_fiche_titre($langs->trans("ListOfMenusEntries"), '', ''); - print 'TODO...'; + // @TODO + print $langs->trans("FeatureNotYetAvailable"); + print '
'; print ''; print ''; @@ -2262,16 +2339,24 @@ elseif (! empty($module)) if ($action != 'editfile' || empty($file)) { - print ''.$langs->trans("PermissionsDefDesc", ''.$langs->trans('DefaultPermissions').'').'
'; + + print ''; + $htmlhelp=$langs->trans("PermissionsDefDescTooltip", ''.$langs->trans('DefaultPermissions').''); + print $form->textwithpicto($langs->trans("PermissionsDefDesc"), $htmlhelp, 1, 'help', '', 0, 2, 'helpondesc').'
'; + print '
'; print '
'; print ' '.$langs->trans("DescriptorFile").' : '.$pathtofile.''; - print ' '.img_picto($langs->trans("Edit"), 'edit').''; + print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; print '
'; print load_fiche_titre($langs->trans("ListOfPermissionsDefined"), '', ''); + + // @TODO + print $langs->trans("FeatureNotYetAvailable"); + print ''; print ''; print ''; @@ -2279,7 +2364,6 @@ elseif (! empty($module)) print ''; print ''; - print 'TODO...'; /* print '
'; print ''; @@ -2391,7 +2475,7 @@ elseif (! empty($module)) $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath']; print ' '.$langs->trans("DescriptorFile").' : '.$pathtofile.''; print ''; print ''; - print ''; + print ''; + print ''; } else { print ''.$langs->trans("FileNotYetGenerated").''; - print ''; + print ''; } print ''; } @@ -2458,8 +2542,8 @@ elseif (! empty($module)) print ''; - print ''; + print ''; + print ''; print ''; } } @@ -2467,7 +2551,7 @@ elseif (! empty($module)) { print ''; + print ''; print ''; } print '
'; - print ''.img_picto($langs->trans("Edit"), 'edit').''; + print ''.img_picto($langs->trans("Edit"), 'edit').''; print '
'; @@ -2400,13 +2484,13 @@ elseif (! empty($module)) if (dol_is_file($dirins.'/'.$pathtohook)) { print ''.$pathtohook.''; - print ''.img_picto($langs->trans("Edit"), 'edit').''.img_picto($langs->trans("Delete"), 'delete').''.img_picto($langs->trans("Edit"), 'edit').''.img_picto($langs->trans("Delete"), 'delete').'
'; print ' '.$langs->trans("TriggersFile").' : '.$pathtofile.''; - print ''.img_picto($langs->trans("Edit"), 'edit').''.img_picto($langs->trans("Delete"), 'delete').''.img_picto($langs->trans("Edit"), 'edit').''.img_picto($langs->trans("Delete"), 'delete').'
'; print ' '.$langs->trans("NoTrigger"); - print '
'; @@ -2518,16 +2602,16 @@ elseif (! empty($module)) $pathtofile = $widget['relpath']; print ' '.$langs->trans("WidgetFile").' : '.$pathtofile.''; - print ' '.img_picto($langs->trans("Edit"), 'edit').''; + print ' '.img_picto($langs->trans("Edit"), 'edit').''; print ''; - print ''.img_picto($langs->trans("Delete"), 'delete').''; + print ''.img_picto($langs->trans("Delete"), 'delete').''; print ''; } } else { print ' '.$langs->trans("NoWidget"); - print ''; + print ''; print ''; } print ''; @@ -2605,15 +2689,15 @@ elseif (! empty($module)) $pathtofile = $clifile['relpath']; print ' '.$langs->trans("CLIFile").' : '.$pathtofile.''; - print ''.img_picto($langs->trans("Edit"), 'edit').''; - print ''.img_picto($langs->trans("Delete"), 'delete').''; + print ''.img_picto($langs->trans("Edit"), 'edit').''; + print ''.img_picto($langs->trans("Delete"), 'delete').''; print ''; } } else { print ' '.$langs->trans("NoCLIFile"); - print ''; + print ''; print ''; } print ''; @@ -2657,7 +2741,7 @@ elseif (! empty($module)) print '
'; print ' '.$langs->trans("DescriptorFile").' : '.$pathtofile.''; - print ' '.img_picto($langs->trans("Edit"), 'edit').''; + print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; print '
'; @@ -2786,8 +2870,8 @@ elseif (! empty($module)) if (preg_match('/\.md$/i', $spec['name'])) $format='markdown'; print ''; print ' '.$langs->trans("SpecificationFile").' : '.$pathtofile.''; - print ''.img_picto($langs->trans("Edit"), 'edit').''; - print ''.img_picto($langs->trans("Delete"), 'delete').''; + print ''.img_picto($langs->trans("Edit"), 'edit').''; + print ''.img_picto($langs->trans("Delete"), 'delete').''; print ''; } } @@ -2795,7 +2879,7 @@ elseif (! empty($module)) { print ''; print ' '.$langs->trans("FileNotYetGenerated"); - print ''; + print ''; print ''; } print ''; @@ -2880,6 +2964,9 @@ elseif (! empty($module)) if ($tab == 'buildpackage') { + print ''.$langs->trans("BuildPackageDesc").''; + print '
'; + if (! class_exists('ZipArchive') && ! defined('ODTPHP_PATHTOPCLZIP')) { print img_warning().' '.$langs->trans("ErrNoZipEngine"); diff --git a/htdocs/modulebuilder/template/class/api_mymodule.class.php b/htdocs/modulebuilder/template/class/api_mymodule.class.php index acf7f65454d..0fcd9a8afd4 100644 --- a/htdocs/modulebuilder/template/class/api_mymodule.class.php +++ b/htdocs/modulebuilder/template/class/api_mymodule.class.php @@ -36,14 +36,6 @@ dol_include_once('/mymodule/class/myobject.class.php'); */ class MyModuleApi extends DolibarrApi { - /** - * @var array $FIELDS Mandatory fields, checked when create and update object - */ - static $FIELDS = array( - 'name', - ); - - /** * @var MyObject $myobject {@type MyObject} */ @@ -75,17 +67,17 @@ class MyModuleApi extends DolibarrApi */ public function get($id) { - if(! DolibarrApiAccess::$user->rights->myobject->read) { + if (! DolibarrApiAccess::$user->rights->mymodule->read) { throw new RestException(401); } $result = $this->myobject->fetch($id); - if( ! $result ) { + if (! $result) { throw new RestException(404, 'MyObject not found'); } - if( ! DolibarrApi::_checkAccessToResource('myobject', $this->myobject->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + if (! DolibarrApi::_checkAccessToResource('myobject', $this->myobject->id, 'mymodule_myobject')) { + throw new RestException(401, 'Access to instance id='.$this->myobject->id.' of object not allowed for login '.DolibarrApiAccess::$user->login); } return $this->_cleanObjectDatas($this->myobject); @@ -113,33 +105,37 @@ class MyModuleApi extends DolibarrApi global $db, $conf; $obj_ret = array(); + $tmpobject = new MyObject($db); + + if(! DolibarrApiAccess::$user->rights->bbb->read) { + throw new RestException(401); + } $socid = DolibarrApiAccess::$user->societe_id ? DolibarrApiAccess::$user->societe_id : ''; - $restictonsocid = 0; // Set to 1 if there is a field socid in table of object + $restrictonsocid = 0; // Set to 1 if there is a field socid in table of object // If the internal user must only see his customers, force searching by him $search_sale = 0; - if ($restictonsocid && ! DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) $search_sale = DolibarrApiAccess::$user->id; + if ($restrictonsocid && ! DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) $search_sale = DolibarrApiAccess::$user->id; $sql = "SELECT t.rowid"; - if ($restictonsocid && (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) $sql .= ", sc.fk_soc, sc.fk_user"; // We need these fields in order to filter by sale (including the case where the user can only see his prospects) - $sql.= " FROM ".MAIN_DB_PREFIX."myobject_mytable as t"; + if ($restrictonsocid && (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) $sql .= ", sc.fk_soc, sc.fk_user"; // We need these fields in order to filter by sale (including the case where the user can only see his prospects) + $sql.= " FROM ".MAIN_DB_PREFIX.$tmpobject->table_element." as t"; - if ($restictonsocid && (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale + if ($restrictonsocid && (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale $sql.= " WHERE 1 = 1"; // Example of use $mode //if ($mode == 1) $sql.= " AND s.client IN (1, 3)"; //if ($mode == 2) $sql.= " AND s.client IN (2, 3)"; - $tmpobject = new MyObject($db); if ($tmpobject->ismultientitymanaged) $sql.= ' AND t.entity IN ('.getEntity('myobject').')'; - if ($restictonsocid && (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) $sql.= " AND t.fk_soc = sc.fk_soc"; - if ($restictonsocid && $socid) $sql.= " AND t.fk_soc = ".$socid; - if ($restictonsocid && $search_sale > 0) $sql.= " AND t.rowid = sc.fk_soc"; // Join for the needed table to filter by sale + if ($restrictonsocid && (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) $sql.= " AND t.fk_soc = sc.fk_soc"; + if ($restrictonsocid && $socid) $sql.= " AND t.fk_soc = ".$socid; + if ($restrictonsocid && $search_sale > 0) $sql.= " AND t.rowid = sc.fk_soc"; // Join for the needed table to filter by sale // Insert sale filter - if ($restictonsocid && $search_sale > 0) { + if ($restrictonsocid && $search_sale > 0) { $sql .= " AND sc.fk_user = ".$search_sale; } if ($sqlfilters) @@ -176,7 +172,7 @@ class MyModuleApi extends DolibarrApi } } else { - throw new RestException(503, 'Error when retrieve myobject list'); + throw new RestException(503, 'Error when retrieving myobject list: '.$db->lasterror()); } if( ! count($obj_ret)) { throw new RestException(404, 'No myobject found'); @@ -194,7 +190,7 @@ class MyModuleApi extends DolibarrApi */ public function post($request_data = null) { - if(! DolibarrApiAccess::$user->rights->myobject->create) { + if(! DolibarrApiAccess::$user->rights->mymodule->write) { throw new RestException(401); } // Check mandatory fields @@ -220,7 +216,7 @@ class MyModuleApi extends DolibarrApi */ public function put($id, $request_data = null) { - if(! DolibarrApiAccess::$user->rights->myobject->create) { + if(! DolibarrApiAccess::$user->rights->mymodule->write) { throw new RestException(401); } @@ -229,8 +225,8 @@ class MyModuleApi extends DolibarrApi throw new RestException(404, 'MyObject not found'); } - if( ! DolibarrApi::_checkAccessToResource('myobject', $this->myobject->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + if( ! DolibarrApi::_checkAccessToResource('myobject', $this->myobject->id, 'mymodule_myobject')) { + throw new RestException(401, 'Access to instance id='.$this->myobject->id.' of object not allowed for login '.DolibarrApiAccess::$user->login); } foreach($request_data as $field => $value) { @@ -254,11 +250,11 @@ class MyModuleApi extends DolibarrApi * @param int $id MyObject ID * @return array * - * @url DELETE myobject/{id} + * @url DELETE myobjects/{id} */ public function delete($id) { - if (! DolibarrApiAccess::$user->rights->myobject->delete) { + if (! DolibarrApiAccess::$user->rights->mymodule->delete) { throw new RestException(401); } $result = $this->myobject->fetch($id); @@ -266,8 +262,8 @@ class MyModuleApi extends DolibarrApi throw new RestException(404, 'MyObject not found'); } - if (! DolibarrApi::_checkAccessToResource('myobject', $this->myobject->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + if (! DolibarrApi::_checkAccessToResource('myobject', $this->myobject->id, 'mymodule_myobject')) { + throw new RestException(401, 'Access to instance id='.$this->myobject->id.' of object not allowed for login '.DolibarrApiAccess::$user->login); } if (! $this->myobject->delete(DolibarrApiAccess::$user)) @@ -317,7 +313,8 @@ class MyModuleApi extends DolibarrApi private function _validate($data) { $myobject = array(); - foreach (MyObjectApi::$FIELDS as $field) { + foreach ($this->myobject->fields as $field => $propfield) { + if (in_array($field, array('rowid', 'entity', 'date_creation', 'tms', 'fk_user_creat')) || $propfield['notnull'] != 1) continue; // Not a mandatory field if (!isset($data[$field])) throw new RestException(400, "$field field missing"); $myobject[$field] = $data[$field]; diff --git a/htdocs/modulebuilder/template/core/modules/modMyModule.class.php b/htdocs/modulebuilder/template/core/modules/modMyModule.class.php index 8a11a6c87b4..2dd29d10195 100644 --- a/htdocs/modulebuilder/template/core/modules/modMyModule.class.php +++ b/htdocs/modulebuilder/template/core/modules/modMyModule.class.php @@ -170,6 +170,7 @@ class modMyModule extends DolibarrModules // 'stock' to add a tab in stock view // 'thirdparty' to add a tab in third party view // 'user' to add a tab in user view + // Dictionaries $this->dictionaries=array(); /* Example: @@ -195,6 +196,7 @@ class modMyModule extends DolibarrModules 'tabcond'=>array($conf->mymodule->enabled,$conf->mymodule->enabled,$conf->mymodule->enabled) ); */ + // Boxes/Widgets // Add here list of php file(s) stored in mymodule/core/boxes that contains class to show a widget. $this->boxes = array( @@ -206,6 +208,7 @@ class modMyModule extends DolibarrModules //1=>array('file'=>'mymodulewidget2.php@mymodule','note'=>'Widget provided by MyModule'), //2=>array('file'=>'mymodulewidget3.php@mymodule','note'=>'Widget provided by MyModule') ); + // Cronjobs (List of cron jobs entries to add when module is enabled) // unit_frequency must be 60 for minute, 3600 for hour, 86400 for day, 604800 for week $this->cronjobs = array( @@ -228,26 +231,28 @@ class modMyModule extends DolibarrModules // 0=>array('label'=>'My label', 'jobtype'=>'method', 'class'=>'/dir/class/file.class.php', 'objectname'=>'MyClass', 'method'=>'myMethod', 'parameters'=>'param1, param2', 'comment'=>'Comment', 'frequency'=>2, 'unitfrequency'=>3600, 'status'=>0, 'test'=>'$conf->mymodule->enabled', 'priority'=>50), // 1=>array('label'=>'My label', 'jobtype'=>'command', 'command'=>'', 'parameters'=>'param1, param2', 'comment'=>'Comment', 'frequency'=>1, 'unitfrequency'=>3600*24, 'status'=>0, 'test'=>'$conf->mymodule->enabled', 'priority'=>50) // ); + // Permissions $this->rights = array(); // Permission array used by this module $r=0; $this->rights[$r][0] = $this->numero + $r; // Permission id (must not be already used) - $this->rights[$r][1] = 'Read myobject of MyModule'; // Permission label + $this->rights[$r][1] = 'Read objects of MyModule'; // Permission label $this->rights[$r][3] = 1; // Permission by default for new user (0/1) $this->rights[$r][4] = 'read'; // In php code, permission will be checked by test if ($user->rights->mymodule->level1->level2) $this->rights[$r][5] = ''; // In php code, permission will be checked by test if ($user->rights->mymodule->level1->level2) $r++; $this->rights[$r][0] = $this->numero + $r; // Permission id (must not be already used) - $this->rights[$r][1] = 'Create/Update myobject of MyModule'; // Permission label + $this->rights[$r][1] = 'Create/Update objects of MyModule'; // Permission label $this->rights[$r][3] = 1; // Permission by default for new user (0/1) $this->rights[$r][4] = 'write'; // In php code, permission will be checked by test if ($user->rights->mymodule->level1->level2) $this->rights[$r][5] = ''; // In php code, permission will be checked by test if ($user->rights->mymodule->level1->level2) $r++; $this->rights[$r][0] = $this->numero + $r; // Permission id (must not be already used) - $this->rights[$r][1] = 'Delete myobject of MyModule'; // Permission label + $this->rights[$r][1] = 'Delete objects of MyModule'; // Permission label $this->rights[$r][3] = 1; // Permission by default for new user (0/1) $this->rights[$r][4] = 'delete'; // In php code, permission will be checked by test if ($user->rights->mymodule->level1->level2) $this->rights[$r][5] = ''; // In php code, permission will be checked by test if ($user->rights->mymodule->level1->level2) + // Main menu entries $this->menu = array(); // List of menus to add $r=0; @@ -298,6 +303,7 @@ class modMyModule extends DolibarrModules 'user'=>2, // 0=Menu for internal users, 1=external users, 2=both ); END MODULEBUILDER LEFTMENU MYOBJECT */ + // Exports $r=1; /* BEGIN MODULEBUILDER EXPORT MYOBJECT */ @@ -317,6 +323,26 @@ class modMyModule extends DolibarrModules $this->export_sql_end[$r] .=' AND t.entity IN ('.getEntity('myobject').')'; $r++; */ /* END MODULEBUILDER EXPORT MYOBJECT */ + + // Imports + $r=1; + /* BEGIN MODULEBUILDER IMPORT MYOBJECT */ + /* + $langs->load("mymodule@mymodule"); + $this->export_code[$r]=$this->rights_class.'_'.$r; + $this->export_label[$r]='MyObjectLines'; // Translation key (used only if key ExportDataset_xxx_z not found) + $this->export_icon[$r]='myobject@mymodule'; + $keyforclass = 'MyObject'; $keyforclassfile='/mymobule/class/myobject.class.php'; $keyforelement='myobject'; + include DOL_DOCUMENT_ROOT.'/core/commonfieldsinexport.inc.php'; + $keyforselect='myobject'; $keyforaliasextra='extra'; $keyforelement='myobject'; + include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php'; + //$this->export_dependencies_array[$r]=array('mysubobject'=>'ts.rowid', 't.myfield'=>array('t.myfield2','t.myfield3')); // To force to activate one or several fields if we select some fields that need same (like to select a unique key if we ask a field of a child to avoid the DISTINCT to discard them, or for computed field than need several other fields) + $this->export_sql_start[$r]='SELECT DISTINCT '; + $this->export_sql_end[$r] =' FROM '.MAIN_DB_PREFIX.'myobject as t'; + $this->export_sql_end[$r] .=' WHERE 1 = 1'; + $this->export_sql_end[$r] .=' AND t.entity IN ('.getEntity('myobject').')'; + $r++; */ + /* END MODULEBUILDER IMPORT MYOBJECT */ } /** * Function called when module is enabled. diff --git a/htdocs/modulebuilder/template/core/triggers/interface_99_modMyModule_MyModuleTriggers.class.php b/htdocs/modulebuilder/template/core/triggers/interface_99_modMyModule_MyModuleTriggers.class.php index 4388c6399db..1718a6a72d5 100644 --- a/htdocs/modulebuilder/template/core/triggers/interface_99_modMyModule_MyModuleTriggers.class.php +++ b/htdocs/modulebuilder/template/core/triggers/interface_99_modMyModule_MyModuleTriggers.class.php @@ -97,7 +97,7 @@ class InterfaceMyModuleTriggers extends DolibarrTriggers */ public function runTrigger($action, $object, User $user, Translate $langs, Conf $conf) { - if (empty($conf->mymodule->enabled)) return 0; // Module not active, we do nothing + if (empty($conf->mymodule->enabled)) return 0; // If module is not enabled, we do nothing // Put here code you want to execute when a Dolibarr business events occurs. // Data and type of action are stored into $object and $action @@ -302,7 +302,9 @@ class InterfaceMyModuleTriggers extends DolibarrTriggers //case 'SHIPPING_CLOSED': //case 'SHIPPING_REOPEN': //case 'SHIPPING_DELETE': - // break; + + // and more... + default: dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); break; diff --git a/htdocs/product/list.php b/htdocs/product/list.php index 39e98730365..0a5508ae725 100644 --- a/htdocs/product/list.php +++ b/htdocs/product/list.php @@ -35,6 +35,7 @@ require '../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php'; if (! empty($conf->categorie->enabled)) require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; diff --git a/htdocs/ticket/agenda.php b/htdocs/ticket/agenda.php index eb863adbfbc..bad8e58497b 100644 --- a/htdocs/ticket/agenda.php +++ b/htdocs/ticket/agenda.php @@ -125,103 +125,102 @@ if (! empty($conf->global->MAIN_HTML_TITLE) && preg_match('/ticketnameonly/', $c $help_url = 'FR:DocumentationModuleTicket'; llxHeader('', $title, $help_url); - if ($socid > 0) { - $object->fetch_thirdparty(); - $head = societe_prepare_head($object->thirdparty); +if ($socid > 0) { + $object->fetch_thirdparty(); + $head = societe_prepare_head($object->thirdparty); - dol_fiche_head($head, 'ticket', $langs->trans("ThirdParty"), 0, 'company'); + dol_fiche_head($head, 'ticket', $langs->trans("ThirdParty"), 0, 'company'); - dol_banner_tab($object->thirdparty, 'socid', '', ($user->societe_id ? 0 : 1), 'rowid', 'nom'); + dol_banner_tab($object->thirdparty, 'socid', '', ($user->societe_id ? 0 : 1), 'rowid', 'nom'); - dol_fiche_end(); - } + dol_fiche_end(); +} - if (!$user->societe_id && $conf->global->TICKET_LIMIT_VIEW_ASSIGNED_ONLY) { - $object->next_prev_filter = "te.fk_user_assign = '" . $user->id . "'"; - } elseif ($user->societe_id > 0) { - $object->next_prev_filter = "te.fk_soc = '" . $user->societe_id . "'"; - } - $head = ticket_prepare_head($object); +if (!$user->societe_id && $conf->global->TICKET_LIMIT_VIEW_ASSIGNED_ONLY) { + $object->next_prev_filter = "te.fk_user_assign = '" . $user->id . "'"; +} elseif ($user->societe_id > 0) { + $object->next_prev_filter = "te.fk_soc = '" . $user->societe_id . "'"; +} +$head = ticket_prepare_head($object); - dol_fiche_head($head, 'tabTicketLogs', $langs->trans("Ticket"), 0, 'ticket'); +dol_fiche_head($head, 'tabTicketLogs', $langs->trans("Ticket"), 0, 'ticket'); - $morehtmlref ='
'; - $morehtmlref.= $object->subject; - // Author - if ($object->fk_user_create > 0) { - $morehtmlref .= '
' . $langs->trans("CreatedBy") . ' '; +$morehtmlref ='
'; +$morehtmlref.= $object->subject; +// Author +if ($object->fk_user_create > 0) { + $morehtmlref .= '
' . $langs->trans("CreatedBy") . ' : '; - $langs->load("users"); - $fuser = new User($db); - $fuser->fetch($object->fk_user_create); - $morehtmlref .= $fuser->getNomUrl(0); - } - if (!empty($object->origin_email)) { - $morehtmlref .= '
' . $langs->trans("CreatedBy") . ' : '; - $morehtmlref .= $object->origin_email . ' (' . $langs->trans("TicketEmailOriginIssuer") . ')'; - } + $langs->load("users"); + $fuser = new User($db); + $fuser->fetch($object->fk_user_create); + $morehtmlref .= $fuser->getNomUrl(0); +} +if (!empty($object->origin_email)) { + $morehtmlref .= '
' . $langs->trans("CreatedBy") . ' : '; + $morehtmlref .= $object->origin_email . ' (' . $langs->trans("TicketEmailOriginIssuer") . ')'; +} - // Thirdparty - if (! empty($conf->societe->enabled)) - { - $morehtmlref.='
'.$langs->trans('ThirdParty'); - /*if ($action != 'editcustomer' && $object->fk_statut < 8 && !$user->societe_id && $user->rights->ticket->write) { - $morehtmlref.='' . img_edit($langs->transnoentitiesnoconv('Edit'), 1) . ''; - }*/ - $morehtmlref.=' : '; - if ($action == 'editcustomer') { - $morehtmlref.=$form->form_thirdparty($url_page_current . '?track_id=' . $object->track_id, $object->socid, 'editcustomer', '', 1, 0, 0, array(), 1); - } else { - $morehtmlref.=$form->form_thirdparty($url_page_current . '?track_id=' . $object->track_id, $object->socid, 'none', '', 1, 0, 0, array(), 1); - } - } +// Thirdparty +if (! empty($conf->societe->enabled)) +{ + $morehtmlref.='
'.$langs->trans('ThirdParty'); + /*if ($action != 'editcustomer' && $object->fk_statut < 8 && !$user->societe_id && $user->rights->ticket->write) { + $morehtmlref.='' . img_edit($langs->transnoentitiesnoconv('Edit'), 1) . ''; + }*/ + $morehtmlref.=' : '; + if ($action == 'editcustomer') { + $morehtmlref.=$form->form_thirdparty($url_page_current . '?track_id=' . $object->track_id, $object->socid, 'editcustomer', '', 1, 0, 0, array(), 1); + } else { + $morehtmlref.=$form->form_thirdparty($url_page_current . '?track_id=' . $object->track_id, $object->socid, 'none', '', 1, 0, 0, array(), 1); + } +} - // Project - if (! empty($conf->projet->enabled)) - { - $langs->load("projects"); - $morehtmlref.='
'.$langs->trans('Project'); - if ($user->rights->ticket->write) - { - if ($action != 'classify') - //$morehtmlref.='' . img_edit($langs->transnoentitiesnoconv('SetProject')) . ''; - $morehtmlref.=' : '; - if ($action == 'classify') { - //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1); - $morehtmlref.=''; - $morehtmlref.=''; - $morehtmlref.=''; - $morehtmlref.=$formproject->select_projects($object->socid, $object->fk_project, 'projectid', 0, 0, 1, 0, 1, 0, 0, '', 1); - $morehtmlref.=''; - $morehtmlref.=''; - } else { - $morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1); - } - } else { - if (! empty($object->fk_project)) { - $proj = new Project($db); - $proj->fetch($object->fk_project); - $morehtmlref.=$proj->getNomUrl(1); - } else { - $morehtmlref.=''; - } - } - } +// Project +if (! empty($conf->projet->enabled)) +{ + $langs->load("projects"); + $morehtmlref.='
'.$langs->trans('Project'); + if ($user->rights->ticket->write) + { + if ($action != 'classify') + //$morehtmlref.='' . img_edit($langs->transnoentitiesnoconv('SetProject')) . ''; + $morehtmlref.=' : '; + if ($action == 'classify') { + //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1); + $morehtmlref.='
'; + $morehtmlref.=''; + $morehtmlref.=''; + $morehtmlref.=$formproject->select_projects($object->socid, $object->fk_project, 'projectid', 0, 0, 1, 0, 1, 0, 0, '', 1); + $morehtmlref.=''; + $morehtmlref.='
'; + } else { + $morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1); + } + } else { + if (! empty($object->fk_project)) { + $proj = new Project($db); + $proj->fetch($object->fk_project); + $morehtmlref.=$proj->getNomUrl(1); + } else { + $morehtmlref.=''; + } + } +} - $morehtmlref.='
'; +$morehtmlref.='
'; - $linkback = '' . $langs->trans("BackToList") . ' '; +$linkback = '' . $langs->trans("BackToList") . ' '; - dol_banner_tab($object, 'ref', $linkback, ($user->societe_id ? 0 : 1), 'ref', 'ref', $morehtmlref, '', 0, '', '', 1); +dol_banner_tab($object, 'ref', $linkback, ($user->societe_id ? 0 : 1), 'ref', 'ref', $morehtmlref, '', 0, '', '', 1); - dol_fiche_end(); +dol_fiche_end(); - print '
'; +print '
'; if (!empty($object->id)) { - print '
'; $param='&id='.$object->id; if (! empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) $param.='&contextpage='.$contextpage; if ($limit > 0 && $limit != $conf->liste_limit) $param.='&limit='.$limit; diff --git a/htdocs/ticket/card.php b/htdocs/ticket/card.php index 44abe008d34..26fec804370 100644 --- a/htdocs/ticket/card.php +++ b/htdocs/ticket/card.php @@ -75,7 +75,7 @@ if (empty($action) && empty($id) && empty($ref)) $action='view'; //Select mail models is same action as add_message if (GETPOST('modelselected', 'alpha')) { - $action = 'add_message'; + $action = 'create_message'; } // Load object @@ -369,9 +369,10 @@ if ($action == "assign_user" && GETPOST('btn_assign_user', 'aplha') && $user->ri $action = 'view'; } -if ($action == "new_message" && GETPOST('btn_add_message') && $user->rights->ticket->read) { - $ret = $object->newMessage($user, $action); - if ($ret) { +if ($action == "add_message" && GETPOST('btn_add_message') && $user->rights->ticket->read) { + $ret = $object->newMessage($user, $action, (GETPOST('private_message', 'alpha') == "on" ? 1 : 0)); + + if ($ret > 0) { if (!empty($backtopage)) { $url = $backtopage; } else { @@ -382,14 +383,10 @@ if ($action == "new_message" && GETPOST('btn_add_message') && $user->rights->tic exit; } else { setEventMessages($object->error, null, 'errors'); - $action = 'add_message'; + $action = 'create_message'; } } -if ($action == "new_public_message" && GETPOST('btn_add_message')) { - $object->newMessagePublic($user, $action); -} - if ($action == "confirm_close" && GETPOST('confirm', 'alpha') == 'yes' && $user->rights->ticket->write) { $object->fetch(GETPOST('id', 'int'), '', GETPOST('track_id', 'alpha')); @@ -641,7 +638,7 @@ if ($action == 'create' || $action == 'presend') $formticket->showForm(1); } -if (empty($action) || $action == 'view' || $action == 'addlink' || $action == 'dellink' || $action == 'add_message' || $action == 'close' || $action == 'delete' || $action == 'editcustomer' || $action == 'progression' || $action == 'reopen' +if (empty($action) || $action == 'view' || $action == 'addlink' || $action == 'dellink' || $action == 'create_message' || $action == 'close' || $action == 'delete' || $action == 'editcustomer' || $action == 'progression' || $action == 'reopen' || $action == 'editsubject' || $action == 'edit_extras' || $action == 'update_extras' || $action == 'edit_extrafields' || $action == 'set_extrafields' || $action == 'classify' || $action == 'sel_contract' || $action == 'edit_message_init' || $action == 'set_status' || $action == 'dellink') { if ($res > 0) @@ -821,7 +818,7 @@ if (empty($action) || $action == 'view' || $action == 'addlink' || $action == 'd $morehtmlref.='
'; - $linkback = '' . $langs->trans("BackToList") . ' '; + $linkback = '' . $langs->trans("BackToList") . ' '; dol_banner_tab($object, 'ref', $linkback, ($user->societe_id ? 0 : 1), 'ref', 'ref', $morehtmlref); @@ -1173,8 +1170,8 @@ if (empty($action) || $action == 'view' || $action == 'addlink' || $action == 'd if (empty($reshook)) { // Show link to add a message (if read and not closed) - if ($object->fk_statut < Ticket::STATUS_CLOSED && $action != "add_message") { - print ''; + if ($object->fk_statut < Ticket::STATUS_CLOSED && $action != "create_message") { + print ''; } // Link to create an intervention @@ -1210,7 +1207,7 @@ if (empty($action) || $action == 'view' || $action == 'addlink' || $action == 'd $action = 'presend'; } - if ($action != 'add_message') + if ($action != 'create_message') { print '
'; print ''; // ancre @@ -1221,10 +1218,10 @@ if (empty($action) || $action == 'view' || $action == 'addlink' || $action == 'd print '
'; - // Message list - print load_fiche_titre($langs->trans('TicketMessagesList'), '', 'messages@ticket'); - $show_private_message = ($user->societe_id ? 0 : 1); - $actionobject->viewTicketTimelineMessages($show_private_message, true, $object); + // List of actions on element + include_once DOL_DOCUMENT_ROOT . '/core/class/html.formactions.class.php'; + $formactions = new FormActions($db); + $somethingshown = $formactions->showactions($object, 'ticket', $socid, 1); print '
'; print '
'; @@ -1232,11 +1229,43 @@ if (empty($action) || $action == 'view' || $action == 'addlink' || $action == 'd } else { - $action='new_message'; + $action='add_message'; // action to use to post the message $modelmail='ticket_send'; + // Substitution array + $morehtmlright=''; + $help=""; + $substitutionarray=array(); + if ($object->fk_soc > 0) { + $object->fetch_thirdparty(); + $substitutionarray['__THIRDPARTY_NAME__'] = $object->thirdparty->name; + } + $substitutionarray['__SIGNATURE__'] = $user->signature; + $substitutionarray['__TICKETSUP_TRACKID__'] = $object->track_id; + $substitutionarray['__TICKETSUP_REF__'] = $object->ref; + $substitutionarray['__TICKETSUP_SUBJECT__'] = $object->subject; + $substitutionarray['__TICKETSUP_TYPE__'] = $object->type_code; + $substitutionarray['__TICKETSUP_SEVERITY__'] = $object->severity_code; + $substitutionarray['__TICKETSUP_CATEGORY__'] = $object->category_code; // For backward compatibility + $substitutionarray['__TICKETSUP_ANALYTIC_CODE__'] = $object->category_code; + $substitutionarray['__TICKETSUP_MESSAGE__'] = $object->message; + $substitutionarray['__TICKETSUP_PROGRESSION__'] = $object->progress; + if ($object->fk_user_assign > 0) { + $userstat->fetch($object->fk_user_assign); + $substitutionarray['__TICKETSUP_USER_ASSIGN__'] = dolGetFirstLastname($userstat->firstname, $userstat->lastname); + } + + if ($object->fk_user_create > 0) { + $userstat->fetch($object->fk_user_create); + $substitutionarray['__TICKETSUP_USER_CREATE__'] = dolGetFirstLastname($userstat->firstname, $userstat->lastname); + } + foreach ($substitutionarray as $key => $val) { + $help.=$key.' -> '.$langs->trans($val).'
'; + } + $morehtmlright.=$form->textwithpicto($langs->trans("TicketMessageSubstitutionReplacedByGenericValues"), $help); + print '
'; - print load_fiche_titre($langs->trans('TicketAddMessage'), '', 'messages@ticket'); + print load_fiche_titre($langs->trans('TicketAddMessage'), $morehtmlright, 'messages@ticket'); print '
'; @@ -1269,30 +1298,7 @@ if (empty($action) || $action == 'view' || $action == 'addlink' || $action == 'd $formticket->withsubstit = 1; - - if ($object->fk_soc > 0) { - $object->fetch_thirdparty(); - $formticket->substit['__THIRDPARTY_NAME__'] = $object->thirdparty->name; - } - $formticket->substit['__SIGNATURE__'] = $user->signature; - $formticket->substit['__TICKETSUP_TRACKID__'] = $object->track_id; - $formticket->substit['__TICKETSUP_REF__'] = $object->ref; - $formticket->substit['__TICKETSUP_SUBJECT__'] = $object->subject; - $formticket->substit['__TICKETSUP_TYPE__'] = $object->type_code; - $formticket->substit['__TICKETSUP_SEVERITY__'] = $object->severity_code; - $formticket->substit['__TICKETSUP_CATEGORY__'] = $object->category_code; // For backward compatibility - $formticket->substit['__TICKETSUP_ANALYTIC_CODE__'] = $object->category_code; - $formticket->substit['__TICKETSUP_MESSAGE__'] = $object->message; - $formticket->substit['__TICKETSUP_PROGRESSION__'] = $object->progress; - if ($object->fk_user_assign > 0) { - $userstat->fetch($object->fk_user_assign); - $formticket->substit['__TICKETSUP_USER_ASSIGN__'] = dolGetFirstLastname($userstat->firstname, $userstat->lastname); - } - - if ($object->fk_user_create > 0) { - $userstat->fetch($object->fk_user_create); - $formticket->substit['__TICKETSUP_USER_CREATE__'] = dolGetFirstLastname($userstat->firstname, $userstat->lastname); - } + $formticket->substit = $substitutionarray; $formticket->showMessageForm('100%'); print '
'; diff --git a/htdocs/ticket/class/actions_ticket.class.php b/htdocs/ticket/class/actions_ticket.class.php index 76049a18a4e..b10f8ebe7da 100644 --- a/htdocs/ticket/class/actions_ticket.class.php +++ b/htdocs/ticket/class/actions_ticket.class.php @@ -443,8 +443,7 @@ class ActionsTicket // Sort results to be similar to status object list //sort($exclude_status); - //print '
'; - foreach ($object->statuts_short as $status => $statut_label) { + foreach ($object->statuts_short as $status => $status_label) { if (!in_array($status, $exclude_status)) { print '
'; diff --git a/htdocs/ticket/class/api_tickets.class.php b/htdocs/ticket/class/api_tickets.class.php index fedadd2c96e..818514868c2 100644 --- a/htdocs/ticket/class/api_tickets.class.php +++ b/htdocs/ticket/class/api_tickets.class.php @@ -123,19 +123,14 @@ class Tickets extends DolibarrApi /** * Get properties of a Ticket object - * * Return an array with ticket informations * * @param int $id ID of ticket * @param string $track_id Tracking ID of ticket * @param string $ref Reference for ticket * @return array|mixed Data without useless information - * - * @throws 401 - * @throws 403 - * @throws 404 */ - public function getCommon($id = 0, $track_id = '', $ref = '') + private function getCommon($id = 0, $track_id = '', $ref = '') { if (! DolibarrApiAccess::$user->rights->ticket->read) { throw new RestException(403); diff --git a/htdocs/ticket/class/ticket.class.php b/htdocs/ticket/class/ticket.class.php index cab2eab92ed..bae523b1819 100644 --- a/htdocs/ticket/class/ticket.class.php +++ b/htdocs/ticket/class/ticket.class.php @@ -207,10 +207,10 @@ class Ticket extends CommonObject */ const STATUS_NOT_READ = 0; const STATUS_READ = 1; - const STATUS_ANSWERED = 3; - const STATUS_ASSIGNED = 4; - const STATUS_IN_PROGRESS = 5; - const STATUS_WAITING = 6; + const STATUS_ASSIGNED = 2; + const STATUS_IN_PROGRESS = 3; + const STATUS_NEED_MORE_INFO = 5; + const STATUS_WAITING = 7; const STATUS_CLOSED = 8; const STATUS_CANCELED = 9; @@ -224,8 +224,8 @@ class Ticket extends CommonObject { $this->db = $db; - $this->statuts_short = array(0 => 'Unread', 1 => 'Read', 3 => 'Answered', 4 => 'Assigned', 5 => 'InProgress', 6 => 'Waiting', 8 => 'Closed', 9 => 'Deleted'); - $this->statuts = array(0 => 'Unread', 1 => 'Read', 3 => 'Answered', 4 => 'Assigned', 5 => 'InProgress', 6 => 'Waiting', 8 => 'Closed', 9 => 'Deleted'); + $this->statuts_short = array(self::STATUS_NOT_READ => 'Unread', self::STATUS_READ => 'Read', self::STATUS_ASSIGNED => 'Assigned', self::STATUS_IN_PROGRESS => 'InProgress', self::STATUS_NEED_MORE_INFO => 'NeedMoreInformation', self::STATUS_WAITING => 'Waiting', self::STATUS_CLOSED => 'Closed', self::STATUS_CANCELED => 'Canceled'); + $this->statuts = array(self::STATUS_NOT_READ => 'Unread', self::STATUS_READ => 'Read', self::STATUS_ASSIGNED => 'Assigned', self::STATUS_IN_PROGRESS => 'InProgress', self::STATUS_NEED_MORE_INFO => 'NeedMoreInformation', self::STATUS_WAITING => 'Waiting', self::STATUS_CLOSED => 'Closed', self::STATUS_CANCELED => 'Canceled'); } /** @@ -906,12 +906,6 @@ class Ticket extends CommonObject if ($res < 0) $error++; } - if (!$error) { - $sql = "DELETE FROM " . MAIN_DB_PREFIX . "ticket_msg"; - $sql .= " WHERE fk_track_id = '" . $this->db->escape($this->track_id) . "'"; - $resql = $this->db->query($sql); - } - // Removed extrafields if (!$error) { $result = $this->deleteExtraFields(); @@ -1176,7 +1170,7 @@ class Ticket extends CommonObject * Return status label of object * * @param string $statut id statut - * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto + * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto * @return string Label */ public function LibStatut($statut, $mode = 0) @@ -1191,134 +1185,106 @@ class Ticket extends CommonObject return $langs->trans($this->statuts_short[$statut]); } elseif ($mode == 2) { - if ($statut == 0) { + if ($statut == self::STATUS_NOT_READ) { return img_picto($langs->trans($this->statuts_short[$statut]), 'statut0.png@ticket') . ' ' . $langs->trans($this->statuts_short[$statut]); } - - elseif ($statut == 1) { + elseif ($statut == self::STATUS_READ) { return img_picto($langs->trans($this->statuts_short[$statut]), 'statut1.png@ticket') . ' ' . $langs->trans($this->statuts_short[$statut]); } - - elseif ($statut == 3) { + elseif ($statut == self::STATUS_ASSIGNED) { + return img_picto($langs->trans($this->statuts_short[$statut]), 'statut2.png@ticket') . ' ' . $langs->trans($this->statuts_short[$statut]); + } + elseif ($statut == self::STATUS_IN_PROGRESS) { return img_picto($langs->trans($this->statuts_short[$statut]), 'statut3.png@ticket') . ' ' . $langs->trans($this->statuts_short[$statut]); } - - elseif ($statut == 4) { - return img_picto($langs->trans($this->statuts_short[$statut]), 'statut4.png@ticket') . ' ' . $langs->trans($this->statuts_short[$statut]); - } - - elseif ($statut == 5) { + elseif ($statut == self::STATUS_NEED_MORE_INFO) { return img_picto($langs->trans($this->statuts_short[$statut]), 'statut5.png@ticket') . ' ' . $langs->trans($this->statuts_short[$statut]); } - - elseif ($statut == 6) { + elseif ($statut == self::STATUS_WAITING) { return img_picto($langs->trans($this->statuts_short[$statut]), 'statut6.png@ticket') . ' ' . $langs->trans($this->statuts_short[$statut]); } - - elseif ($statut == 8) { + elseif ($statut == self::STATUS_CLOSED) { return img_picto($langs->trans($this->statuts_short[$statut]), 'statut8.png@ticket') . ' ' . $langs->trans($this->statuts_short[$statut]); } - - elseif ($statut == 9) { + elseif ($statut == self::STATUS_CANCELED) { return img_picto($langs->trans($this->statuts_short[$statut]), 'statut9.png@ticket') . ' ' . $langs->trans($this->statuts_short[$statut]); } } elseif ($mode == 3) { - if ($statut == 0) { + if ($statut == self::STATUS_NOT_READ) { return img_picto($langs->trans($this->statuts_short[$statut]), 'statut0.png@ticket'); } - - elseif ($statut == 1) { + elseif ($statut == self::STATUS_READ) { return img_picto($langs->trans($this->statuts_short[$statut]), 'statut1.png@ticket'); } - - elseif ($statut == 3) { + elseif ($statut == self::STATUS_ASSIGNED) { + return img_picto($langs->trans($this->statuts_short[$statut]), 'statut2.png@ticket'); + } + elseif ($statut == self::STATUS_IN_PROGRESS) { return img_picto($langs->trans($this->statuts_short[$statut]), 'statut3.png@ticket'); } - - elseif ($statut == 4) { - return img_picto($langs->trans($this->statuts_short[$statut]), 'statut4.png@ticket'); - } - - elseif ($statut == 5) { + elseif ($statut == self::STATUS_NEED_MORE_INFO) { return img_picto($langs->trans($this->statuts_short[$statut]), 'statut5.png@ticket'); } - - elseif ($statut == 6) { + elseif ($statut == self::STATUS_WAITING) { return img_picto($langs->trans($this->statuts_short[$statut]), 'statut6.png@ticket'); } - - elseif ($statut == 8) { + elseif ($statut == self::STATUS_CLOSED) { return img_picto($langs->trans($this->statuts_short[$statut]), 'statut8.png@ticket'); } - - elseif ($statut == 9) { + elseif ($statut == self::STATUS_CANCELED) { return img_picto($langs->trans($this->statuts_short[$statut]), 'statut9.png@ticket'); } } elseif ($mode == 4) { - if ($statut == 0) { + if ($statut == self::STATUS_NOT_READ) { return img_picto($langs->trans($this->statuts_short[$statut]), 'statut0.png@ticket') . ' ' . $langs->trans($this->statuts_short[$statut]); } - - elseif ($statut == 1) { + elseif ($statut == self::STATUS_READ) { return img_picto($langs->trans($this->statuts_short[$statut]), 'statut1.png@ticket') . ' ' . $langs->trans($this->statuts_short[$statut]); } - - elseif ($statut == 3) { + elseif ($statut == self::STATUS_ASSIGNED) { + return img_picto($langs->trans($this->statuts_short[$statut]), 'statut2.png@ticket') . ' ' . $langs->trans($this->statuts_short[$statut]); + } + elseif ($statut == self::STATUS_IN_PROGRESS) { return img_picto($langs->trans($this->statuts_short[$statut]), 'statut3.png@ticket') . ' ' . $langs->trans($this->statuts_short[$statut]); } - - elseif ($statut == 4) { - return img_picto($langs->trans($this->statuts_short[$statut]), 'statut4.png@ticket') . ' ' . $langs->trans($this->statuts_short[$statut]); - } - - elseif ($statut == 5) { + elseif ($statut == self::STATUS_NEED_MORE_INFO) { return img_picto($langs->trans($this->statuts_short[$statut]), 'statut5.png@ticket') . ' ' . $langs->trans($this->statuts_short[$statut]); } - - elseif ($statut == 6) { + elseif ($statut == self::STATUS_WAITING) { return img_picto($langs->trans($this->statuts_short[$statut]), 'statut6.png@ticket') . ' ' . $langs->trans($this->statuts_short[$statut]); } - - elseif ($statut == 8) { + elseif ($statut == self::STATUS_CLOSED) { return img_picto($langs->trans($this->statuts_short[$statut]), 'statut8.png@ticket') . ' ' . $langs->trans($this->statuts_short[$statut]); } - - elseif ($statut == 9) { + elseif ($statut == self::STATUS_CANCELED) { return img_picto($langs->trans($this->statuts_short[$statut]), 'statut9.png@ticket') . ' ' . $langs->trans($this->statuts_short[$statut]); } } - elseif ($mode == 5) { - if ($statut == 0) { + elseif ($mode == 5 || $mode == 6) { + if ($statut == self::STATUS_NOT_READ) { return $langs->trans($this->statuts_short[$statut]) . ' ' . img_picto($langs->trans($this->statuts_short[$statut]), 'statut0.png@ticket'); } - - elseif ($statut == 1) { + elseif ($statut == self::STATUS_READ) { return $langs->trans($this->statuts_short[$statut]) . ' ' . img_picto($langs->trans($this->statuts_short[$statut]), 'statut1.png@ticket'); } - - elseif ($statut == 3) { + elseif ($statut == self::STATUS_ASSIGNED) { + return $langs->trans($this->statuts_short[$statut]) . ' ' . img_picto($langs->trans($this->statuts_short[$statut]), 'statut2.png@ticket'); + } + elseif ($statut == self::STATUS_IN_PROGRESS) { return $langs->trans($this->statuts_short[$statut]) . ' ' . img_picto($langs->trans($this->statuts_short[$statut]), 'statut3.png@ticket'); } - - elseif ($statut == 4) { - return $langs->trans($this->statuts_short[$statut]) . ' ' . img_picto($langs->trans($this->statuts_short[$statut]), 'statut4.png@ticket'); - } - - elseif ($statut == 5) { + elseif ($statut == self::STATUS_NEED_MORE_INFO) { return $langs->trans($this->statuts_short[$statut]) . ' ' . img_picto($langs->trans($this->statuts_short[$statut]), 'statut5.png@ticket'); } - - elseif ($statut == 6) { + elseif ($statut == self::STATUS_WAITING) { return $langs->trans($this->statuts_short[$statut]) . ' ' . img_picto($langs->trans($this->statuts_short[$statut]), 'statut6.png@ticket'); } - - elseif ($statut == 8) { + elseif ($statut == self::STATUS_CLOSED) { return $langs->trans($this->statuts_short[$statut]) . ' ' . img_picto($langs->trans($this->statuts_short[$statut]), 'statut8.png@ticket'); } - - elseif ($statut == 9) { + elseif ($statut == self::STATUS_CANCELED) { return $langs->trans($this->statuts_short[$statut]) . ' ' . img_picto($langs->trans($this->statuts_short[$statut]), 'statut9.png@ticket'); } } @@ -1645,6 +1611,8 @@ class Ticket extends CommonObject global $conf, $langs; $error = 0; + $now = dol_now(); + // Clean parameters if (isset($this->fk_track_id)) { $this->fk_track_id = trim($this->fk_track_id); @@ -1654,50 +1622,33 @@ class Ticket extends CommonObject $this->message = trim($this->message); } - // Insert request - $sql = "INSERT INTO " . MAIN_DB_PREFIX . "ticket_msg("; - - $sql .= "fk_track_id,"; - $sql .= "fk_user_action,"; - $sql .= "datec,"; - $sql .= "message,"; - $sql .= "private"; - $sql .= ") VALUES ("; - $sql .= " " . (!isset($this->fk_track_id) ? "'" . $this->db->escape($this->track_id) . "'" : "'" . $this->db->escape($this->fk_track_id) . "'") . ","; - $sql .= " " . ($this->fk_user_action > 0 ? $this->fk_user_action : $user->id) . ","; - $sql .= " '" . $this->db->idate(dol_now()) . "',"; - $sql .= " " . (!isset($this->message) ? 'NULL' : "'" . $this->db->escape($this->message) . "'") . ","; - $sql .= " " . (empty($this->private) ? '0' : "'" . $this->db->escape($this->private) . "'") . ""; - $sql .= ")"; - $this->db->begin(); - dol_syslog(get_class($this) . "::create_ticket_message sql=" . $sql, LOG_DEBUG); - $resql = $this->db->query($sql); - if (!$resql) { - $error++; - $this->errors[] = "Error " . $this->db->lasterror(); - } + // Insert entry into agenda with code 'TICKET_MSG' + include_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php'; + $actioncomm=new ActionComm($this->db); + $actioncomm->type_code = 'AC_OTH_AUTO'; + $actioncomm->code = 'TICKET_MSG'; + $actioncomm->socid = $this->socid; + $actioncomm->label = $this->subject; + $actioncomm->note = $this->message; + $actioncomm->userassigned = array($user->id); + $actioncomm->userownerid = $user->id; + $actioncomm->datep = $now; + $actioncomm->percentage = 100; + $actioncomm->elementtype = 'ticket'; + $actioncomm->fk_element = $this->id; - if (!$error) { - if (!$notrigger) { - // Uncomment this and change MYOBJECT to your own tag if you - // want this action calls a trigger. - //// Call triggers - //include_once DOL_DOCUMENT_ROOT . '/core/class/interfaces.class.php'; - //$interface=new Interfaces($this->db); - //$result=$interface->run_triggers('MYOBJECT_CREATE',$this,$user,$langs,$conf); - //if ($result < 0) { $error++; $this->errors=$interface->errors; } - //// End call triggers - } + $actionid = $actioncomm->create($user); + if ($actionid <= 0) + { + $error++; + $this->error = $actioncomm->error; + $this->errors = $actioncomm->errors; } // Commit or rollback if ($error) { - foreach ($this->errors as $errmsg) { - dol_syslog(get_class($this) . "::create_ticket_message " . $errmsg, LOG_ERR); - $this->error .= ($this->error ? ', ' . $errmsg : $errmsg); - } $this->db->rollback(); return -1 * $error; } else { @@ -1720,12 +1671,13 @@ class Ticket extends CommonObject } // Cache deja charge - $sql = "SELECT rowid, fk_user_action, datec, message, private"; - $sql .= " FROM " . MAIN_DB_PREFIX . "ticket_msg"; - $sql .= " WHERE fk_track_id ='" . $this->db->escape($this->track_id) . "'"; + $sql = "SELECT rowid, fk_user_author, datec, label, message, visibility"; + $sql .= " FROM " . MAIN_DB_PREFIX . "actioncomm"; + $sql .= " WHERE fk_element = " . (int) $this->id; + $sql .= " AND elementtype = 'ticket'"; $sql .= " ORDER BY datec DESC"; - dol_syslog(get_class($this) . "::load_cache_actions_ticket sql=" . $sql, LOG_DEBUG); + dol_syslog(get_class($this) . "::load_cache_actions_ticket sql=" . $sql, LOG_DEBUG); $resql = $this->db->query($sql); if ($resql) { $num = $this->db->num_rows($resql); @@ -1735,8 +1687,9 @@ class Ticket extends CommonObject $this->cache_msgs_ticket[$i]['id'] = $obj->rowid; $this->cache_msgs_ticket[$i]['fk_user_action'] = $obj->fk_user_action; $this->cache_msgs_ticket[$i]['datec'] = $this->db->jdate($obj->datec); + $this->cache_msgs_ticket[$i]['subject'] = $obj->label; $this->cache_msgs_ticket[$i]['message'] = $obj->message; - $this->cache_msgs_ticket[$i]['private'] = $obj->private; + $this->cache_msgs_ticket[$i]['private'] = ($obj->visibility == 'private' ? 1 : 0); $i++; } return $num; @@ -2486,11 +2439,12 @@ class Ticket extends CommonObject /** * Add new message on a ticket (private area) * - * @param User $user User for action - * @param string $action Action string - * @return int + * @param User $user User for action + * @param string $action Action string + * @param int $private 1=Message is private. TODO Implement this. What does this means ? + * @return int */ - public function newMessage($user, &$action) + public function newMessage($user, &$action, $private = 1) { global $mysoc, $conf, $langs; @@ -2504,6 +2458,7 @@ class Ticket extends CommonObject $error = 0; $ret = $object->fetch('', '', GETPOST('track_id', 'alpha')); + $object->socid = $object->fk_soc; $object->fetch_thirdparty(); if ($ret < 0) { @@ -2519,8 +2474,9 @@ class Ticket extends CommonObject } if (!$error) { - $object->message = GETPOST("message"); - $object->private = GETPOST("private_message"); + $object->subject = GETPOST('subject', 'alphanohtml'); + $object->message = GETPOST("message", "none"); + $object->private = GETPOST("private_message", "alpha"); $send_email = GETPOST('send_email', 'int'); $id = $object->createTicketMessage($user); @@ -2777,152 +2733,6 @@ class Ticket extends CommonObject setEventMessages($langs->trans('ErrorMailRecipientIsEmptyForSendTicketMessage'), null, 'warnings'); } } - - /** - * Add new message on a ticket (public area) - * - * @param User $user User for action - * @param string $action Action string - * @return void - */ - public function newMessagePublic($user, &$action) - { - global $mysoc, $conf, $langs; - - $object = new Ticket($this->db); - - $error = 0; - $ret = $object->fetch('', '', GETPOST('track_id', 'alpha')); - $object->socid = $object->fk_soc; - $object->fetch_thirdparty(); - if ($ret < 0) { - $error++; - array_push($this->errors, $langs->trans("ErrorTicketIsNotValid")); - $action = ''; - } - - if (!GETPOST("message")) { - $error++; - array_push($this->errors, $langs->trans("ErrorFieldRequired", $langs->transnoentities("message"))); - $action = 'add_message'; - } - - if (!$error) { - $object->message = (string) GETPOST("message"); - $id = $object->createTicketMessage($user); - if ($id <= 0) { - $error++; - $this->error = $object->error; - $this->errors = $object->errors; - $action = 'add_message'; - } - - if (!$error && $id > 0) { - setEventMessages($langs->trans('TicketMessageSuccessfullyAdded'), null, 'mesgs'); - - // Retrieve internal contact datas - $internal_contacts = $object->getInfosTicketInternalContact(); - $sendto = array(); - if (is_array($internal_contacts) && count($internal_contacts) > 0) { - $subject = '[' . $mysoc->name . '- ticket #' . $object->track_id . '] ' . $langs->trans('TicketNewMessage'); - - $message = $langs->trans('TicketMessageMailIntroAutoNewPublicMessage', $object->subject); - $message .= "\n"; - $message .= GETPOST('message'); - $message .= "\n"; - - // Coordonnées client - if ($object->thirdparty->id > 0) { - $message .= "\n\n"; - $message .= "==============================================\n"; - $message .= $langs->trans('Thirparty') . " : " . $object->thirdparty->name; - $message .= !empty($object->thirdparty->town) ? $langs->trans('Town') . " : " . $object->thirdparty->town : ''; - $message .= "\n"; - $message .= !empty($object->thirdparty->phone) ? $langs->trans('Phone') . " : " . $object->thirdparty->phone : ''; - $message .= "\n"; - } - - // Build array to display recipient list - foreach ($internal_contacts as $key => $info_sendto) { - if ($info_sendto['email'] != '') { - $sendto[] = trim($info_sendto['firstname'] . " " . $info_sendto['lastname']) . " <" . $info_sendto['email'] . ">"; - } - - // Contact type - $recipient = dolGetFirstLastname($info_sendto['firstname'], $info_sendto['lastname'], '-1') . ' (' . strtolower($info_sendto['libelle']) . ')'; - $message .= (!empty($recipient) ? $langs->trans('TicketNotificationRecipient') . ' : ' . $recipient . "\n" : ''); - $message .= "\n"; - } - - // URL ticket - $url_internal_ticket = dol_buildpath('/ticket/card.php', 2) . '?track_id=' . $object->track_id; - $message .= "\n" . $langs->trans('TicketNotificationEmailBodyInfosTrackUrlinternal') . ' : ' . $url_internal_ticket . "\n"; - - $message .= "\n\n"; - - $message_signature = GETPOST('mail_signature') ? GETPOST('mail_signature') : $conf->global->TICKET_MESSAGE_MAIL_SIGNATURE; - - // Add global email address reciepient - if ($conf->global->TICKET_NOTIFICATION_ALSO_MAIN_ADDRESS && !in_array($conf->global->TICKET_NOTIFICATION_EMAIL_FROM, $sendto)) { - $sendto[] = $conf->global->TICKET_NOTIFICATION_EMAIL_FROM; - } - - $this->sendTicketMessageByEmail($subject, $message, '', $sendto); - } - - /* - * Email for externals users if not private - */ - - // Retrieve email of all contacts external - $external_contacts = $object->getInfosTicketExternalContact(); - $sendto = array(); - if (is_array($external_contacts) && count($external_contacts) > 0) { - $subject = '[' . $mysoc->name . '- ticket #' . $object->track_id . '] ' . $langs->trans('TicketNewMessage'); - - $message = $langs->trans('TicketMessageMailIntroAutoNewPublicMessage', $object->subject); - $message .= "\n"; - - $message .= GETPOST('message'); - $message .= "\n\n"; - - $message_signature = GETPOST('mail_signature') ? GETPOST('mail_signature') : $conf->global->TICKET_MESSAGE_MAIL_SIGNATURE; - foreach ($external_contacts as $key => $info_sendto) { - if ($info_sendto['email'] != '') { - $sendto[] = trim($info_sendto['firstname'] . " " . $info_sendto['lastname']) . " <" . $info_sendto['email'] . ">"; - } - $recipient = ''; - $recipient = dolGetFirstLastname($info_sendto['firstname'], $info_sendto['lastname'], '-1') . ' (' . strtolower($info_sendto['libelle']) . ')'; - $message .= (!empty($recipient) ? $langs->trans('TicketNotificationRecipient') . ' : ' . $recipient . "\n" : ''); - } - - $url_public_ticket = ($conf->global->TICKET_URL_PUBLIC_INTERFACE ? $conf->global->TICKET_URL_PUBLIC_INTERFACE . '/view.php' : dol_buildpath('/public/ticket/view.php', 2)) . '?track_id=' . $object->track_id; - $message .= "\n\n" . $langs->trans('TicketNewEmailBodyInfosTrackUrlCustomer') . ' : ' . $url_public_ticket . "\n"; - - // Add signature - $message .= '\n\n' . $message_signature; - - if (!empty($object->origin_email) && !in_array($object->origin_email, $sendto)) { - $sendto[] = $object->origin_email; - } - if ($object->fk_soc > 0 && !in_array($object->origin_email, $sendto)) { - $sendto[] = $object->thirdparty->email; - } - $this->sendTicketMessageByEmail($subject, $message, '', $sendto); - } - - $object->copyFilesForTicket(); - - $url = 'view.php?action=view_ticket&track_id=' . $object->track_id; - header("Location: " . $url); - exit; - } else { - setEventMessages($object->error, $object->errors, 'errors'); - } - } else { - setEventMessages($this->error, $this->errors, 'errors'); - } - } } diff --git a/htdocs/ticket/img/statut0.png b/htdocs/ticket/img/statut0.png index 6e631dc0086..b1cf5df0e75 100644 Binary files a/htdocs/ticket/img/statut0.png and b/htdocs/ticket/img/statut0.png differ diff --git a/htdocs/ticket/img/statut1.png b/htdocs/ticket/img/statut1.png index 5bff8090beb..4e72abd23cc 100644 Binary files a/htdocs/ticket/img/statut1.png and b/htdocs/ticket/img/statut1.png differ diff --git a/htdocs/ticket/img/statut4.png b/htdocs/ticket/img/statut2.png similarity index 100% rename from htdocs/ticket/img/statut4.png rename to htdocs/ticket/img/statut2.png diff --git a/htdocs/ticket/img/statut3.png b/htdocs/ticket/img/statut3.png index 4e72abd23cc..6ea7f62a9ff 100644 Binary files a/htdocs/ticket/img/statut3.png and b/htdocs/ticket/img/statut3.png differ diff --git a/htdocs/ticket/img/statut5.png b/htdocs/ticket/img/statut5.png index 6ea7f62a9ff..6e631dc0086 100644 Binary files a/htdocs/ticket/img/statut5.png and b/htdocs/ticket/img/statut5.png differ diff --git a/htdocs/ticket/img/statut6.png b/htdocs/ticket/img/statut6.png index af7f6d433dc..5bff8090beb 100644 Binary files a/htdocs/ticket/img/statut6.png and b/htdocs/ticket/img/statut6.png differ diff --git a/htdocs/ticket/img/statut8.png b/htdocs/ticket/img/statut8.png index 84f3c5e7fc5..af7f6d433dc 100644 Binary files a/htdocs/ticket/img/statut8.png and b/htdocs/ticket/img/statut8.png differ diff --git a/htdocs/ticket/img/statut9.png b/htdocs/ticket/img/statut9.png new file mode 100644 index 00000000000..84f3c5e7fc5 Binary files /dev/null and b/htdocs/ticket/img/statut9.png differ