diff --git a/ChangeLog b/ChangeLog index ae767c91649..76709bd8f85 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,9 +4,20 @@ English Dolibarr ChangeLog ***** ChangeLog for 17.0.0 compared to 16.0.0 ***** +For users: +--------------- + +... + + For developers or integrators: ------------------------------ +... + + +WARNING: + Following changes may create regressions for some external modules, but were necessary to make Dolibarr better: * The signature of method getNomUrl() of class ProductFournisseur has been modified to match the signature of method Product @@ -192,6 +203,8 @@ NEW: Add hooks select product list and select thirdparty list function NEW: Add hook to getSellPrice function +WARNING: + Following changes may create regressions for some external modules, but were necessary to make Dolibarr better: * There is a new specific permission to be allowed to enter timesheets. If you use timesheet, don't forget to give the new permission (disable and enable the module project if it is not visible). @@ -489,6 +502,8 @@ NEW: we need to be able to put more filters on deleteByParentField() function NEW: make it easier to set the `keyword`, `keywords` and `description` attributes of an ecm file object NEW: Experimental feature to manage user sessions in database + +WARNING: Following changes may create regressions for some external modules, but were necessary to make Dolibarr better: * ALL EXTERNAL MODULES THAT WERE NOT CORRECTLY DEVELOPPED WILL NOT WORK ON V15 (All modules that forgot to manage the security token field diff --git a/htdocs/adherents/list.php b/htdocs/adherents/list.php index 3075225abb9..1995485eb4e 100644 --- a/htdocs/adherents/list.php +++ b/htdocs/adherents/list.php @@ -63,6 +63,7 @@ $search_email = GETPOST("search_email", 'alpha'); $search_categ = GETPOST("search_categ", 'int'); $search_filter = GETPOST("search_filter", 'alpha'); $search_status = GETPOST("search_status", 'intcomma'); +$search_morphy = GETPOST("search_morphy", 'alpha'); $search_import_key = trim(GETPOST("search_import_key", "alpha")); $catid = GETPOST("catid", 'int'); $optioncss = GETPOST('optioncss', 'alpha'); @@ -382,6 +383,9 @@ if ($search_status != '') { // Peut valoir un nombre ou liste de nombre separes par virgules $sql .= " AND d.statut in (".$db->sanitize($db->escape($search_status)).")"; } +if ($search_morphy != '') { + $sql .= natural_search("d.morphy", $search_morphy); +} if ($search_ref) { $sql .= natural_search("d.ref", $search_ref); } @@ -731,6 +735,11 @@ if (!empty($arrayfields['d.login']['checked'])) { } if (!empty($arrayfields['d.morphy']['checked'])) { print ''; + $arraymorphy = array('mor'=>$langs->trans("Moral"), 'phy'=>$langs->trans("Physical")); + print $form->selectarray('search_morphy', $arraymorphy, $search_morphy, 1); + print ''; +} +if (!empty($arrayfields['t.libelle']['checked'])) { print ''; } if (!empty($arrayfields['t.libelle']['checked'])) { diff --git a/htdocs/admin/clicktodial.php b/htdocs/admin/clicktodial.php index 326e7028bbf..a8d33ae5a09 100644 --- a/htdocs/admin/clicktodial.php +++ b/htdocs/admin/clicktodial.php @@ -47,8 +47,9 @@ if (!in_array('clicktodial', $conf->modules)) { if ($action == 'setvalue' && $user->admin) { $result1 = dolibarr_set_const($db, "CLICKTODIAL_USE_TEL_LINK_ON_PHONE_NUMBERS", GETPOST("CLICKTODIAL_USE_TEL_LINK_ON_PHONE_NUMBERS"), 'chaine', 0, '', $conf->entity); $result2 = dolibarr_set_const($db, "CLICKTODIAL_URL", GETPOST("CLICKTODIAL_URL"), 'chaine', 0, '', $conf->entity); + $result3 = dolibarr_set_const($db, "CLICKTODIAL_KEY_FOR_CIDLOOKUP", GETPOST("CLICKTODIAL_KEY_FOR_CIDLOOKUP"), 'chaine', 0, '', $conf->entity); - if ($result1 >= 0 && $result2 >= 0) { + if ($result1 >= 0 && $result2 >= 0 && $result3 >= 0) { setEventMessages($langs->trans("SetupSaved"), null, 'mesgs'); } else { setEventMessages($langs->trans("Error"), null, 'errors'); @@ -80,7 +81,7 @@ print ''; print '
'; print ''; print ''; -print ''; +print ''; print ''; print "\n"; @@ -89,21 +90,21 @@ print ''; print ''; +print ''; +print ''; +print ''; +print ''; + print '
'.$langs->trans("Name").''.$langs->trans("Name").''.$langs->trans("Value").'
'; print $langs->trans("ClickToDialUseTelLink").''; print $form->selectyesno("CLICKTODIAL_USE_TEL_LINK_ON_PHONE_NUMBERS", $conf->global->CLICKTODIAL_USE_TEL_LINK_ON_PHONE_NUMBERS, 1).'
'; print '
'; -print $langs->trans("ClickToDialUseTelLinkDesc"); +print ''.$langs->trans("ClickToDialUseTelLinkDesc").''; print '
'; print $langs->trans("DefaultLink").''; -print 'global->CLICKTODIAL_USE_TEL_LINK_ON_PHONE_NUMBERS ? ' disabled="disabled"' : '').' value="'.$conf->global->CLICKTODIAL_URL.'">
'; +print '
'; print ajax_autoselect('CLICKTODIAL_URL'); print '
'; print $langs->trans("ClickToDialUrlDesc").'
'; print '
'; print ''; print $langs->trans("Examples").':
'; -print 'https://myphoneserver/mypage?login=__LOGIN__&password=__PASS__&caller=__PHONEFROM__&called=__PHONETO__
'; -print 'sip:__PHONETO__@my.sip.server'; +print '* https://myphoneserver/phoneurl?login=__LOGIN__&password=__PASS__&caller=__PHONEFROM__&called=__PHONETO__
'; +print '* sip:__PHONETO__@my.sip.server'; print '
'; //if (! empty($user->clicktodial_url)) @@ -114,6 +115,37 @@ print ''; print '
'.$langs->trans("SecurityKey").''; + +global $dolibarr_main_url_root; + +// Define $urlwithroot +$urlwithouturlroot = preg_replace('/'.preg_quote(DOL_URL_ROOT, '/').'$/i', '', trim($dolibarr_main_url_root)); +$urlwithroot = $urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file +//$urlwithroot=DOL_MAIN_URL_ROOT; // This is to use same domain name than current + +// Url for CIDLookup +//print '
'; +//print $langs->trans("URLToLaunchCronJobs").':
'; +$url = $urlwithroot.'/public/clicktodial/cidlookup.php?securitykey='.getDolGlobalString('CLICKTODIAL_KEY_FOR_CIDLOOKUP', 'ValueToDefine').'&phone=...'; +//print img_picto('', 'globe').' '.$url."
\n"; +//print '
'; +//print '
'; + + +print ''.$langs->trans("CIDLookupURL").''; +print '
'.$url; +print '
'; +print '
'; +print ''; +if (!empty($conf->use_javascript_ajax)) { + print ' '.img_picto($langs->trans('Generate'), 'refresh', 'id="generate_token" class="linkobject"'); +} +print '
'; print '
'; @@ -156,6 +188,23 @@ if (!empty($conf->global->CLICKTODIAL_URL)) { } } +if (!empty($conf->use_javascript_ajax)) { + print "\n".''; +} + // End of page llxFooter(); $db->close(); diff --git a/htdocs/admin/dict.php b/htdocs/admin/dict.php index 6453210e596..fa5d6deae97 100644 --- a/htdocs/admin/dict.php +++ b/htdocs/admin/dict.php @@ -2090,6 +2090,8 @@ if ($id > 0) { $valuetoshow = $langs->trans($obj->{$value}); } elseif ($value == 'block_if_negative') { $valuetoshow = yn($obj->{$value}); + } elseif ($value == 'icon') { + $valuetoshow = $obj->{$value}." ".img_picto("", $obj->{$value}); } elseif ($value == 'type_duration') { $TDurationTypes = array('y'=>$langs->trans('Years'), 'm'=>$langs->trans('Month'), 'w'=>$langs->trans('Weeks'), 'd'=>$langs->trans('Days'), 'h'=>$langs->trans('Hours'), 'i'=>$langs->trans('Minutes')); $valuetoshow =$TDurationTypes[$obj->{$value}]; diff --git a/htdocs/admin/mails_emailing.php b/htdocs/admin/mails_emailing.php index 40af4c4ae2a..79ddda792e0 100644 --- a/htdocs/admin/mails_emailing.php +++ b/htdocs/admin/mails_emailing.php @@ -427,11 +427,15 @@ if ($action == 'edit') { // Method print ''.$langs->trans("MAIN_MAIL_SENDMODE").''; - $text = $listofmethods[$conf->global->MAIN_MAIL_SENDMODE_EMAILING]; + $text = $listofmethods[getDolGlobalString('MAIN_MAIL_SENDMODE_EMAILING')]; if (empty($text)) { $text = $langs->trans("Undefined").img_warning(); } - print $text; + if (getDolGlobalString('MAIN_MAIL_SENDMODE_EMAILING') == 'default') { + print ''.$text.''; + } else { + print $text; + } print ''; if (!empty($conf->global->MAIN_MAIL_SENDMODE_EMAILING) && $conf->global->MAIN_MAIL_SENDMODE_EMAILING != 'default') { diff --git a/htdocs/admin/mails_ticket.php b/htdocs/admin/mails_ticket.php index 481fcad212c..a439bdabcf0 100644 --- a/htdocs/admin/mails_ticket.php +++ b/htdocs/admin/mails_ticket.php @@ -394,11 +394,15 @@ if ($action == 'edit') { // Method print ''.$langs->trans("MAIN_MAIL_SENDMODE").''; - $text = $listofmethods[$conf->global->MAIN_MAIL_SENDMODE_TICKET]; + $text = $listofmethods[getDolGlobalString('MAIN_MAIL_SENDMODE_TICKET')]; if (empty($text)) { $text = $langs->trans("Undefined").img_warning(); } - print $text; + if (getDolGlobalString('MAIN_MAIL_SENDMODE_TICKET') == 'default') { + print ''.$text.''; + } else { + print $text; + } print ''; if (!empty($conf->global->MAIN_MAIL_SENDMODE_TICKET) && $conf->global->MAIN_MAIL_SENDMODE_TICKET != 'default') { diff --git a/htdocs/admin/system/constall.php b/htdocs/admin/system/constall.php index 96cb98809ef..9a27feb3d7a 100644 --- a/htdocs/admin/system/constall.php +++ b/htdocs/admin/system/constall.php @@ -89,6 +89,7 @@ $configfileparameters = array( 'separator', '?dolibarr_mailing_limit_sendbyweb', '?dolibarr_mailing_limit_sendbycli', + '?dolibarr_mailing_limit_sendbyday', '?dolibarr_strict_mode' ); $configfilelib = array( diff --git a/htdocs/admin/system/dolibarr.php b/htdocs/admin/system/dolibarr.php index e58cf45dd7e..8a982f6e0bd 100644 --- a/htdocs/admin/system/dolibarr.php +++ b/htdocs/admin/system/dolibarr.php @@ -360,6 +360,7 @@ $configfileparameters = array( 'dolibarr_main_restrict_ip' => 'Restrict access to some IPs only', '?dolibarr_mailing_limit_sendbyweb' => 'Limit nb of email sent by page', '?dolibarr_mailing_limit_sendbycli' => 'Limit nb of email sent by cli', + '?dolibarr_mailing_limit_sendbyday' => 'Limit nb of email sent per day', '?dolibarr_strict_mode' => 'Strict mode is on/off', '?dolibarr_nocsrfcheck' => 'Disable CSRF security checks' ); diff --git a/htdocs/api/index.php b/htdocs/api/index.php index afb0289aa32..8543e284533 100644 --- a/htdocs/api/index.php +++ b/htdocs/api/index.php @@ -257,6 +257,8 @@ if (!empty($reg[1]) && $reg[1] == 'explorer' && ($reg[2] == '/swagger.json' || $ continue; } + //dol_syslog("We scan to search api file with into ".$dir_part.$file_searched); + $regapi = array(); if (is_readable($dir_part.$file_searched) && preg_match("/^api_(.*)\.class\.php$/i", $file_searched, $regapi)) { $classname = ucwords($regapi[1]); diff --git a/htdocs/comm/mailing/card.php b/htdocs/comm/mailing/card.php index d46a02132a1..748c5fabf10 100644 --- a/htdocs/comm/mailing/card.php +++ b/htdocs/comm/mailing/card.php @@ -801,13 +801,20 @@ if ($action == 'create') { // MAILING_NO_USING_PHPMAIL may be defined or not. // MAILING_LIMIT_SENDBYWEB is always defined to something != 0 (-1=forbidden). // MAILING_LIMIT_SENDBYCLI may be defined ot not (-1=forbidden, 0 or undefined=no limit). + // MAILING_LIMIT_SENDBYDAY may be defined ot not (0 or undefined=no limit). if (!empty($conf->global->MAILING_NO_USING_PHPMAIL) && $sendingmode == 'mail') { // EMailing feature may be a spam problem, so when you host several users/instance, having this option may force each user to use their own SMTP agent. // You ensure that every user is using its own SMTP server when using the mass emailing module. $linktoadminemailbefore = ''; $linktoadminemailend = ''; setEventMessages($langs->trans("MailSendSetupIs", $listofmethods[$sendingmode]), null, 'warnings'); - setEventMessages($langs->trans("MailSendSetupIs2", $linktoadminemailbefore, $linktoadminemailend, $langs->transnoentitiesnoconv("MAIN_MAIL_SENDMODE"), $listofmethods['smtps']), null, 'warnings'); + $messagetoshow = $langs->trans("MailSendSetupIs2", '{s1}', '{s2}', '{s3}', '{s4}'); + $messagetoshow = str_replace('{s1}', $linktoadminemailbefore, $messagetoshow); + $messagetoshow = str_replace('{s2}', $linktoadminemailend, $messagetoshow); + $messagetoshow = str_replace('{s3}', $langs->transnoentitiesnoconv("MAIN_MAIL_SENDMODE"), $messagetoshow); + $messagetoshow = str_replace('{s4}', $listofmethods['smtps'], $messagetoshow); + setEventMessages($messagetoshow, null, 'warnings'); + if (!empty($conf->global->MAILING_SMTP_SETUP_EMAILS_FOR_QUESTIONS)) { setEventMessages($langs->trans("MailSendSetupIs3", $conf->global->MAILING_SMTP_SETUP_EMAILS_FOR_QUESTIONS), null, 'warnings'); } @@ -836,14 +843,21 @@ if ($action == 'create') { } $text = ''; - if (!isset($conf->global->MAILING_LIMIT_SENDBYCLI) || $conf->global->MAILING_LIMIT_SENDBYCLI >= 0) { - $text .= $langs->trans("MailingNeedCommand"); - $text .= '
'; + + if (isset($conf->global->MAILING_LIMIT_SENDBYDAY) && $conf->global->MAILING_LIMIT_SENDBYDAY >= 0) { + $text .= $langs->trans('WarningLimitSendByDay', $conf->global->MAILING_LIMIT_SENDBYDAY); $text .= '

'; } $text .= $langs->trans('ConfirmSendingEmailing').'
'; $text .= $langs->trans('LimitSendingEmailing', $conf->global->MAILING_LIMIT_SENDBYWEB); - print $form->formconfirm($_SERVER['PHP_SELF'].'?id='.$object->id, $langs->trans('SendMailing'), $text, 'sendallconfirmed', '', '', 1, 330, 600); + + if (!isset($conf->global->MAILING_LIMIT_SENDBYCLI) || $conf->global->MAILING_LIMIT_SENDBYCLI >= 0) { + $text .= '

'; + $text .= $langs->trans("MailingNeedCommand"); + $text .= '
'; + } + + print $form->formconfirm($_SERVER['PHP_SELF'].'?id='.$object->id, $langs->trans('SendMailing'), $text, 'sendallconfirmed', '', '', 1, 330, 600, 0, $langs->trans("Confirm"), $langs->trans("Cancel")); } } diff --git a/htdocs/contact/card.php b/htdocs/contact/card.php index 5cdc0d0c6e4..06149063806 100644 --- a/htdocs/contact/card.php +++ b/htdocs/contact/card.php @@ -1301,11 +1301,10 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { $action = 'presend'; } + // View mode if (!empty($id) && $action != 'edit' && $action != 'create') { $objsoc = new Societe($db); - // View mode - // Show errors dol_htmloutput_errors(is_numeric($error) ? '' : $error, $errors); @@ -1530,9 +1529,12 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { if ($object->user_id) { $dolibarr_user = new User($db); $result = $dolibarr_user->fetch($object->user_id); - print $dolibarr_user->getLoginUrl(1); + print $dolibarr_user->getLoginUrl(-1); } else { - print $langs->trans("NoDolibarrAccess"); + //print ''.$langs->trans("NoDolibarrAccess").''; + if (!$object->user_id && $user->rights->user->user->creer) { + print ''.img_picto($langs->trans("CreateDolibarrLogin"), 'add').' '.$langs->trans("CreateDolibarrLogin").''; + } } print ''; @@ -1565,10 +1567,6 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { print ''.$langs->trans('Modify').''; } - if (!$object->user_id && $user->rights->user->user->creer) { - print ''.$langs->trans("CreateDolibarrLogin").''; - } - // Activer if ($object->statut == 0 && $user->rights->societe->contact->creer) { print ''.$langs->trans("Reactivate").''; diff --git a/htdocs/contrat/class/contrat.class.php b/htdocs/contrat/class/contrat.class.php index 322f3f4652e..1e8da8a9a81 100644 --- a/htdocs/contrat/class/contrat.class.php +++ b/htdocs/contrat/class/contrat.class.php @@ -668,7 +668,7 @@ class Contrat extends CommonObject if (!$id) { $sql .= " WHERE entity IN (".getEntity('contract').")"; } else { - $sql .= " WHERE rowid=".(int) $id; + $sql .= " WHERE rowid = ".(int) $id; } if ($ref_customer) { $sql .= " AND ref_customer = '".$this->db->escape($ref_customer)."'"; @@ -677,7 +677,7 @@ class Contrat extends CommonObject $sql .= " AND ref_supplier = '".$this->db->escape($ref_supplier)."'"; } if ($ref) { - $sql .= " AND ref='".$this->db->escape($ref)."'"; + $sql .= " AND ref = '".$this->db->escape($ref)."'"; } dol_syslog(get_class($this)."::fetch", LOG_DEBUG); @@ -724,10 +724,13 @@ class Contrat extends CommonObject // Retrieve all extrafields // fetch optionals attributes and labels - $this->fetch_optionals(); + $result = $this->fetch_optionals(); // Lines - $result = $this->fetch_lines(); + if ($result >= 0 && !empty($this->table_element_line)) { + $result = $this->fetch_lines(); + } + if ($result < 0) { $this->error = $this->db->lasterror(); return -3; diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 4d83acfe44c..b0ea04adb3e 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -7633,16 +7633,24 @@ abstract class CommonObject } if ($result > 0) { if ($object->element === 'product') { - $getnomurlparam3 = (!isset($InfoFieldList[5]) ? 0 : $InfoFieldList[5]); - $getnomurlparam4 = (!isset($InfoFieldList[6]) ? -1 : $InfoFieldList[6]); - $getnomurlparam5 = (!isset($InfoFieldList[7]) ? 0 : $InfoFieldList[7]); - $getnomurlparam6 = (!isset($InfoFieldList[8]) ? '' : $InfoFieldList[8]); - $getnomurlparam7 = (!isset($InfoFieldList[9]) ? 0 : $InfoFieldList[9]); + $get_name_url_param_arr = array($getnomurlparam, $getnomurlparam2, 0, -1, 0, '', 0); + if (isset($val['get_name_url_params'])) { + $get_name_url_params = explode(':', $val['get_name_url_params']); + if (!empty($get_name_url_params)) { + $param_num_max = count($get_name_url_param_arr) - 1; + foreach ($get_name_url_params as $param_num => $param_value) { + if ($param_num > $param_num_max) { + break; + } + $get_name_url_param_arr[$param_num] = $param_value; + } + } + } /** * @var Product $object */ - $value = $object->getNomUrl($getnomurlparam, $getnomurlparam2, $getnomurlparam3, $getnomurlparam4, $getnomurlparam5, $getnomurlparam6, $getnomurlparam7); + $value = $object->getNomUrl($get_name_url_param_arr[0], $get_name_url_param_arr[1], $get_name_url_param_arr[2], $get_name_url_param_arr[3], $get_name_url_param_arr[4], $get_name_url_param_arr[5], $get_name_url_param_arr[6]); } else { $value = $object->getNomUrl($getnomurlparam, $getnomurlparam2); } diff --git a/htdocs/core/class/conf.class.php b/htdocs/core/class/conf.class.php index 22a6f8da7a4..2e544a9953a 100644 --- a/htdocs/core/class/conf.class.php +++ b/htdocs/core/class/conf.class.php @@ -1038,12 +1038,15 @@ class Conf if (!empty($this->file->mailing_limit_sendbyweb)) { $this->global->MAILING_LIMIT_SENDBYWEB = $this->file->mailing_limit_sendbyweb; } - if (empty($this->global->MAILING_LIMIT_SENDBYWEB)) { + if (empty($this->global->MAILING_LIMIT_SENDBYWEB)) { // Limit by web can't be 0 $this->global->MAILING_LIMIT_SENDBYWEB = 25; } if (!empty($this->file->mailing_limit_sendbycli)) { $this->global->MAILING_LIMIT_SENDBYCLI = $this->file->mailing_limit_sendbycli; } + if (!empty($this->file->mailing_limit_sendbyday)) { + $this->global->MAILING_LIMIT_SENDBYDAY = $this->file->mailing_limit_sendbyday; + } return 0; } diff --git a/htdocs/core/class/dolgraph.class.php b/htdocs/core/class/dolgraph.class.php index 2fe60cc323c..e24afd73879 100644 --- a/htdocs/core/class/dolgraph.class.php +++ b/htdocs/core/class/dolgraph.class.php @@ -1316,7 +1316,7 @@ class DolGraph if (empty($showlegend)) { $this->stringtoshow .= 'legend: { display: false }, '."\n"; } else { - $this->stringtoshow .= 'legend: { maxWidth: '.round($this->width / 2).', labels: { boxWidth: 15 }, position: \'' . ($showlegend == 2 ? 'right' : 'top') . '\' },'."\n"; + $this->stringtoshow .= 'legend: { maxWidth: '.round(intVal($this->width) / 2).', labels: { boxWidth: 15 }, position: \'' . (($showlegend && $showlegend == 2) ? 'right' : 'top') . '\' },'."\n"; } $this->stringtoshow .= "}, \n"; diff --git a/htdocs/core/class/extrafields.class.php b/htdocs/core/class/extrafields.class.php index f2463804e32..c12cfc480fc 100644 --- a/htdocs/core/class/extrafields.class.php +++ b/htdocs/core/class/extrafields.class.php @@ -908,7 +908,7 @@ class ExtraFields $this->attributes[$tab->elementtype]['param'][$tab->name] = ($tab->param ? jsonOrUnserialize($tab->param) : ''); $this->attributes[$tab->elementtype]['pos'][$tab->name] = $tab->pos; $this->attributes[$tab->elementtype]['alwayseditable'][$tab->name] = $tab->alwayseditable; - $this->attributes[$tab->elementtype]['perms'][$tab->name] = (strlen($tab->perms) == 0 ? 1 : $tab->perms); + $this->attributes[$tab->elementtype]['perms'][$tab->name] = ((is_null($tab->perms) || strlen($tab->perms) == 0) ? 1 : $tab->perms); $this->attributes[$tab->elementtype]['langfile'][$tab->name] = $tab->langs; $this->attributes[$tab->elementtype]['list'][$tab->name] = $tab->list; $this->attributes[$tab->elementtype]['printable'][$tab->name] = $tab->printable; diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 68bca2606b7..625791ea0d0 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -3342,7 +3342,6 @@ class Form } $outref = $objp->ref; - $outval = ''; $outbarcode = $objp->barcode; $outqty = 1; $outdiscount = 0; @@ -3523,48 +3522,52 @@ class Form } } - $opt = '\n"; // Add new entry // "key" value of json key array is used by jQuery automatically as selected value. Example: 'type' = product or service, 'price_ht' = unit price without tax // "label" value of json key array is used by jQuery automatically as text for combo box - $out .= $opt; - array_push( - $outarray, - array('key'=>$outkey, - 'value'=>$outref, - 'label'=>$outval, - 'qty'=>$outqty, - 'price_qty_ht'=>price2num($objp->fprice, 'MU'), // Keep higher resolution for price for the min qty - 'price_unit_ht'=>price2num($objp->unitprice, 'MU'), // This is used to fill the Unit Price - 'price_ht'=>price2num($objp->unitprice, 'MU'), // This is used to fill the Unit Price (for compatibility) - 'tva_tx'=>$objp->tva_tx, - 'default_vat_code'=>$objp->default_vat_code, - 'discount'=>$outdiscount, - 'type'=>$outtype, - 'duration_value'=>$outdurationvalue, - 'duration_unit'=>$outdurationunit, - 'disabled'=>(empty($objp->idprodfournprice) ? true : false), - 'description'=>$objp->description - ) - ); + $out .= $optstart . ' data-html="'.dol_escape_htmltag($optlabel).'">' . $optlabel . "\n";; + array_push($outarray, $outarrayentry); + // Exemple of var_dump $outarray // array(1) {[0]=>array(6) {[key"]=>string(1) "2" ["value"]=>string(3) "ppp" // ["label"]=>string(76) "ppp (fff2) - ppp - 20,00 Euros/1unité (20,00 Euros/unité)" diff --git a/htdocs/core/class/html.formcompany.class.php b/htdocs/core/class/html.formcompany.class.php index 32f2a9b1007..2a900ea53a4 100644 --- a/htdocs/core/class/html.formcompany.class.php +++ b/htdocs/core/class/html.formcompany.class.php @@ -825,13 +825,14 @@ class FormCompany extends Form /** * showContactRoles on view and edit mode * - * @param string $htmlname Html component name and id - * @param Contact $contact Contact Obejct - * @param string $rendermode view, edit - * @param array $selected $key=>$val $val is selected Roles for input mode - * @return string String with contacts roles + * @param string $htmlname Html component name and id + * @param Contact $contact Contact Obejct + * @param string $rendermode view, edit + * @param array $selected $key=>$val $val is selected Roles for input mode + * @param string $morecss More css + * @return string String with contacts roles */ - public function showRoles($htmlname, Contact $contact, $rendermode = 'view', $selected = array()) + public function showRoles($htmlname, Contact $contact, $rendermode = 'view', $selected = array(), $morecss = 'minwidth500') { if ($rendermode === 'view') { $toprint = array(); @@ -856,7 +857,7 @@ class FormCompany extends Form $selected = $newselected; } } - return $this->multiselectarray($htmlname, $contactType, $selected, 0, 0, 'minwidth500'); + return $this->multiselectarray($htmlname, $contactType, $selected, 0, 0, $morecss); } return 'ErrorBadValueForParameterRenderMode'; // Should not happened diff --git a/htdocs/core/class/html.formmail.class.php b/htdocs/core/class/html.formmail.class.php index df7408200a9..4c77566eeed 100644 --- a/htdocs/core/class/html.formmail.class.php +++ b/htdocs/core/class/html.formmail.class.php @@ -954,7 +954,7 @@ class FormMail extends Form $out .= ''; } else { if (!isset($this->ckeditortoolbar)) { - $this->ckeditortoolbar = 'dolibarr_notes'; + $this->ckeditortoolbar = 'dolibarr_mailings'; } // Editor wysiwyg diff --git a/htdocs/core/class/html.formother.class.php b/htdocs/core/class/html.formother.class.php index 5bee2f31dd4..103b370dcb0 100644 --- a/htdocs/core/class/html.formother.class.php +++ b/htdocs/core/class/html.formother.class.php @@ -1513,9 +1513,10 @@ class FormOther * @param array $search_xaxis Array of preselected fields * @param array $arrayofxaxis Array of groupby to fill * @param string $showempty '1' or 'text' + * @param string $morecss More css * @return string HTML string component */ - public function selectXAxisField($object, $search_xaxis, &$arrayofxaxis, $showempty = '1') + public function selectXAxisField($object, $search_xaxis, &$arrayofxaxis, $showempty = '1', $morecss = 'minwidth250 maxwidth500') { global $form; @@ -1523,7 +1524,7 @@ class FormOther foreach ($arrayofxaxis as $key => $val) { $arrayofxaxislabel[$key] = $val['label']; } - $result = $form->selectarray('search_xaxis', $arrayofxaxislabel, $search_xaxis, $showempty, 0, 0, '', 0, 0, 0, '', 'minwidth250 maxwidth500', 1); + $result = $form->selectarray('search_xaxis', $arrayofxaxislabel, $search_xaxis, $showempty, 0, 0, '', 0, 0, 0, '', $morecss, 1); return $result; } diff --git a/htdocs/core/customreports.php b/htdocs/core/customreports.php index 46b885bd60a..c1222a6b762 100644 --- a/htdocs/core/customreports.php +++ b/htdocs/core/customreports.php @@ -217,7 +217,7 @@ foreach ($arrayoftype as $key => $val) { if (dol_eval($val['enabled'], 1, 1, '1')) { $newarrayoftype[$key] = $arrayoftype[$key]; } - if ($val['langs']) { + if (!empty($val['langs'])) { $langs->load($val['langs']); } } @@ -450,7 +450,7 @@ $simplearrayofmesures = array(); foreach ($arrayofmesures as $key => $val) { $simplearrayofmesures[$key] = $arrayofmesures[$key]['label']; } -print $form->multiselectarray('search_measures', $simplearrayofmesures, $search_measures, 0, 0, 'minwidth400', 1, 0, '', '', $langs->trans("Measures")); // Fill the array $arrayofmeasures with possible fields +print $form->multiselectarray('search_measures', $simplearrayofmesures, $search_measures, 0, 0, 'minwidth300', 1, 0, '', '', $langs->trans("Measures")); // Fill the array $arrayofmeasures with possible fields print ''; // XAxis @@ -458,7 +458,7 @@ $count = 0; print '
'; print '
'; //var_dump($arrayofxaxis); -print $formother->selectXAxisField($object, $search_xaxis, $arrayofxaxis, $langs->trans("XAxis")); // Fill the array $arrayofxaxis with possible fields +print $formother->selectXAxisField($object, $search_xaxis, $arrayofxaxis, $langs->trans("XAxis"), 'minwidth300 maxwidth400'); // Fill the array $arrayofxaxis with possible fields print '
'; // Group by @@ -970,31 +970,31 @@ function fillArrayOfMeasures($object, $tablealias, $labelofobject, &$arrayofmesu // Add main fields of object foreach ($object->fields as $key => $val) { if (!empty($val['isameasure']) && (!isset($val['enabled']) || dol_eval($val['enabled'], 1, 1, '1'))) { - $position = (!empty($val['position']) ? $val['position'] : 0); + $position = (empty($val['position']) ? 0 : intVal($val['position'])); $arrayofmesures[$tablealias.'.'.$key.'-sum'] = array( 'label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val['label']).' ('.$langs->trans("Sum").')', - 'position' => ($position+($count * 100000)).'.1', + 'position' => ($position + ($count * 100000)).'.1', 'table' => $object->table_element ); $arrayofmesures[$tablealias.'.'.$key.'-average'] = array( 'label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val['label']).' ('.$langs->trans("Average").')', - 'position' => ($position+($count * 100000)).'.2', + 'position' => ($position + ($count * 100000)).'.2', 'table' => $object->table_element ); $arrayofmesures[$tablealias.'.'.$key.'-min'] = array( 'label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val['label']).' ('.$langs->trans("Minimum").')', - 'position' => ($position+($count * 100000)).'.3', + 'position' => ($position + ($count * 100000)).'.3', 'table' => $object->table_element ); $arrayofmesures[$tablealias.'.'.$key.'-max'] = array( 'label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val['label']).' ('.$langs->trans("Maximum").')', - 'position' => ($position+($count * 100000)).'.4', + 'position' => ($position + ($count * 100000)).'.4', 'table' => $object->table_element ); } } // Add extrafields to Measures - if ($object->isextrafieldmanaged) { + if (!empty($object->isextrafieldmanaged)) { foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) { if (!empty($extrafields->attributes[$object->table_element]['totalizable'][$key]) && (!isset($extrafields->attributes[$object->table_element]['enabled'][$key]) || dol_eval($extrafields->attributes[$object->table_element]['enabled'][$key], 1, 1, '1'))) { $position = (!empty($val['position']) ? $val['position'] : 0); @@ -1098,26 +1098,27 @@ function fillArrayOfXAxis($object, $tablealias, $labelofobject, &$arrayofxaxis, continue; } if (in_array($val['type'], array('timestamp', 'date', 'datetime'))) { - $position = (!empty($val['position']) ? $val['position'] : 0); + $position = (empty($val['position']) ? 0 : intVal($val['position'])); $arrayofxaxis[$tablealias.'.'.$key.'-year'] = array( 'label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val['label']).' ('.$YYYY.')', - 'position' => ($position+($count * 100000)).'.1', + 'position' => ($position + ($count * 100000)).'.1', 'table' => $object->table_element ); $arrayofxaxis[$tablealias.'.'.$key.'-month'] = array( 'label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val['label']).' ('.$YYYY.'-'.$MM.')', - 'position' => ($position+($count * 100000)).'.2', + 'position' => ($position + ($count * 100000)).'.2', 'table' => $object->table_element ); $arrayofxaxis[$tablealias.'.'.$key.'-day'] = array( 'label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val['label']).' ('.$YYYY.'-'.$MM.'-'.$DD.')', - 'position' => ($position+($count * 100000)).'.3', + 'position' => ($position + ($count * 100000)).'.3', 'table' => $object->table_element ); } else { + $position = (empty($val['position']) ? 0 : intVal($val['position'])); $arrayofxaxis[$tablealias.'.'.$key] = array( 'label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val['label']), - 'position' => ($position+($count * 100000)), + 'position' => ($position + ($count * 100000)), 'table' => $object->table_element ); } @@ -1125,7 +1126,7 @@ function fillArrayOfXAxis($object, $tablealias, $labelofobject, &$arrayofxaxis, } // Add extrafields to X-Axis - if ($object->isextrafieldmanaged) { + if (!empty($object->isextrafieldmanaged)) { foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) { if ($extrafields->attributes[$object->table_element]['type'][$key] == 'separate') { continue; @@ -1196,7 +1197,7 @@ function fillArrayOfGroupBy($object, $tablealias, $labelofobject, &$arrayofgroup // Add main fields of object foreach ($object->fields as $key => $val) { - if (!$val['isameasure']) { + if (empty($val['isameasure'])) { if (in_array($key, array( 'id', 'ref_int', 'ref_ext', 'rowid', 'entity', 'last_main_doc', 'logo', 'logo_squarred', 'extraparams', 'parent', 'photo', 'socialnetworks', 'webservices_url', 'webservices_key'))) { @@ -1218,26 +1219,27 @@ function fillArrayOfGroupBy($object, $tablealias, $labelofobject, &$arrayofgroup continue; } if (in_array($val['type'], array('timestamp', 'date', 'datetime'))) { - $position = (!empty($val['position']) ? $val['position'] : 0); + $position = (empty($val['position']) ? 0 : intVal($val['position'])); $arrayofgroupby[$tablealias.'.'.$key.'-year'] = array( 'label' => img_picto('', $object->picto, - 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val['label']).' ('.$YYYY.')', 'position' => ($position+($count * 100000)).'.1', + 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val['label']).' ('.$YYYY.')', 'position' => ($position + ($count * 100000)).'.1', 'table' => $object->table_element ); $arrayofgroupby[$tablealias.'.'.$key.'-month'] = array( 'label' => img_picto('', $object->picto, - 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val['label']).' ('.$YYYY.'-'.$MM.')', 'position' => ($position+($count * 100000)).'.2', + 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val['label']).' ('.$YYYY.'-'.$MM.')', 'position' => ($position + ($count * 100000)).'.2', 'table' => $object->table_element ); $arrayofgroupby[$tablealias.'.'.$key.'-day'] = array( 'label' => img_picto('', $object->picto, - 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val['label']).' ('.$YYYY.'-'.$MM.'-'.$DD.')', 'position' => ($position+($count * 100000)).'.3', + 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val['label']).' ('.$YYYY.'-'.$MM.'-'.$DD.')', 'position' => ($position + ($count * 100000)).'.3', 'table' => $object->table_element ); } else { + $position = (empty($val['position']) ? 0 : intVal($val['position'])); $arrayofgroupby[$tablealias.'.'.$key] = array( 'label' => img_picto('', $object->picto, - 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val['label']), 'position' => ($position+($count * 100000)), + 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val['label']), 'position' => ($position + ($count * 100000)), 'table' => $object->table_element ); } @@ -1245,7 +1247,7 @@ function fillArrayOfGroupBy($object, $tablealias, $labelofobject, &$arrayofgroup } // Add extrafields to Group by - if ($object->isextrafieldmanaged) { + if (! empty($object->isextrafieldmanaged)) { foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) { if ($extrafields->attributes[$object->table_element]['type'][$key] == 'separate') { continue; diff --git a/htdocs/core/lib/company.lib.php b/htdocs/core/lib/company.lib.php index 03c1aa4afdf..908dacb870c 100644 --- a/htdocs/core/lib/company.lib.php +++ b/htdocs/core/lib/company.lib.php @@ -777,7 +777,7 @@ function isInEEC($object) */ function show_projects($conf, $langs, $db, $object, $backtopage = '', $nocreatelink = 0, $morehtmlright = '') { - global $user; + global $user, $action, $hookmanager; $i = -1; @@ -791,8 +791,9 @@ function show_projects($conf, $langs, $db, $object, $backtopage = '', $nocreatel print "\n"; print load_fiche_titre($langs->trans("ProjectsDedicatedToThisThirdParty"), $newcardbutton.$morehtmlright, ''); - print '
'; - print "\n".''; + + print '
'."\n"; + print '
'; $sql = "SELECT p.rowid as id, p.entity, p.title, p.ref, p.public, p.dateo as do, p.datee as de, p.fk_statut as status, p.fk_opp_status, p.opp_amount, p.opp_percent, p.tms as date_update, p.budget_amount"; $sql .= ", cls.code as opp_status_code"; @@ -877,6 +878,11 @@ function show_projects($conf, $langs, $db, $object, $backtopage = '', $nocreatel } else { dol_print_error($db); } + + $parameters = array('sql'=>$sql, 'function'=>'show_projects'); + $reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object, $action); // Note that $action and $object may have been modified by hook + print $hookmanager->resPrint; + print "
"; print '
'; @@ -890,14 +896,15 @@ function show_projects($conf, $langs, $db, $object, $backtopage = '', $nocreatel /** * Show html area for list of contacts * - * @param Conf $conf Object conf - * @param Translate $langs Object langs - * @param DoliDB $db Database handler - * @param Societe $object Third party object - * @param string $backtopage Url to go once contact is created + * @param Conf $conf Object conf + * @param Translate $langs Object langs + * @param DoliDB $db Database handler + * @param Societe $object Third party object + * @param string $backtopage Url to go once contact is created + * @param int $showuserlogin 1=Show also user login if it exists * @return int */ -function show_contacts($conf, $langs, $db, $object, $backtopage = '') +function show_contacts($conf, $langs, $db, $object, $backtopage = '', $showuserlogin = 0) { global $user, $conf, $extrafields, $hookmanager; global $contextpage; @@ -1131,13 +1138,16 @@ function show_contacts($conf, $langs, $db, $object, $backtopage = '') if (in_array($key, array('statut'))) { print $form->selectarray('search_status', array('-1'=>'', '0'=>$contactstatic->LibStatut(0, 1), '1'=>$contactstatic->LibStatut(1, 1)), $search_status); } elseif (in_array($key, array('role'))) { - print $formcompany->showRoles("search_roles", $contactstatic, 'edit', $search_roles); + print $formcompany->showRoles("search_roles", $contactstatic, 'edit', $search_roles, 'minwidth200 maxwidth300'); } else { print ''; } print ''; } } + if ($showuserlogin) { + print ''; + } // Extra fields $extrafieldsobjectkey = $contactstatic->table_element; include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php'; @@ -1177,6 +1187,9 @@ function show_contacts($conf, $langs, $db, $object, $backtopage = '') print getTitleFieldOfList($arrayfields['sc.'.$key]['label'], 0, $_SERVER['PHP_SELF'], '', '', $param, ($align ? 'class="'.$align.'"' : ''), $sortfield, $sortorder, $align.' ')."\n"; } } + if ($showuserlogin) { + print ''.$langs->trans("DolibarrLogin").''; + } // Extra fields $extrafieldsobjectkey = $contactstatic->table_element; include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php'; @@ -1275,6 +1288,16 @@ function show_contacts($conf, $langs, $db, $object, $backtopage = '') print ''.$contactstatic->getLibStatut(5).''; } + if ($showuserlogin) { + print ''; + $tmpuser= new User($db); + $resfetch = $tmpuser->fetch(0, '', '', 0, -1, '', $contactstatic->id); + if ($resfetch > 0) { + print $tmpuser->getNomUrl(1, '', 0, 0, 24, 1); + } + print ''; + } + // Extra fields $extrafieldsobjectkey = $contactstatic->table_element; include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 381280289ee..51d26491826 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -3887,15 +3887,18 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $ if (strpos($pictowithouttext, 'fontawesome_') !== false || preg_match('/^fa-/', $pictowithouttext)) { // This is a font awesome image 'fonwtawesome_xxx' or 'fa-xxx' + $pictowithouttext = str_replace('fontawesome_', '', $pictowithouttext); $pictowithouttext = str_replace('fa-', '', $pictowithouttext); + $pictowithouttextarray = explode('_', $pictowithouttext); $marginleftonlyshort = 0; if (!empty($pictowithouttextarray[1])) { - $fakey = 'fa-'.$pictowithouttextarray[1]; - $fa = empty($pictowithouttextarray[2]) ? 'fa' : $pictowithouttextarray[2]; - $facolor = empty($pictowithouttextarray[3]) ? '' : $pictowithouttextarray[3]; - $fasize = empty($pictowithouttextarray[4]) ? '' : $pictowithouttextarray[4]; + // Syntax is 'fontawesome_fakey_faprefix_facolor_fasize' or 'fa-fakey_faprefix_facolor_fasize' + $fakey = 'fa-'.$pictowithouttextarray[0]; + $fa = empty($pictowithouttextarray[1]) ? 'fa' : $pictowithouttextarray[1]; + $facolor = empty($pictowithouttextarray[2]) ? '' : $pictowithouttextarray[2]; + $fasize = empty($pictowithouttextarray[3]) ? '' : $pictowithouttextarray[3]; } else { $fakey = 'fa-'.$pictowithouttext; $fa = 'fa'; diff --git a/htdocs/core/lib/modulebuilder.lib.php b/htdocs/core/lib/modulebuilder.lib.php index a775569407a..9e17d925dbe 100644 --- a/htdocs/core/lib/modulebuilder.lib.php +++ b/htdocs/core/lib/modulebuilder.lib.php @@ -30,7 +30,7 @@ * @param string $objectname Name of object * @param string $newmask New mask * @param string $readdir Directory source (use $destdir when not defined) - * @param string $addfieldentry Array of the field entry to add array('key'=>,'type'=>,''label'=>,'visible'=>,'enabled'=>,'position'=>,'notnull'=>','index'=>,'searchall'=>,'comment'=>,'help'=>,'isameasure') + * @param string $addfieldentry Array of 1 field entry to add array('key'=>,'type'=>,''label'=>,'visible'=>,'enabled'=>,'position'=>,'notnull'=>','index'=>,'searchall'=>,'comment'=>,'help'=>,'isameasure') * @param string $delfieldentry Id of field to remove * @return int|object <=0 if KO, Object if OK * @see rebuildObjectSql() @@ -40,7 +40,7 @@ function rebuildObjectClass($destdir, $module, $objectname, $newmask, $readdir = global $db, $langs; if (empty($objectname)) { - return -1; + return -6; } if (empty($readdir)) { $readdir = $destdir; @@ -48,9 +48,11 @@ function rebuildObjectClass($destdir, $module, $objectname, $newmask, $readdir = if (!empty($addfieldentry['arrayofkeyval']) && !is_array($addfieldentry['arrayofkeyval'])) { dol_print_error('', 'Bad parameter addfieldentry with a property arrayofkeyval defined but that is not an array.'); - return -1; + return -7; } + $error = 0; + // Check parameters if (is_array($addfieldentry) && count($addfieldentry) > 0) { if (empty($addfieldentry['name'])) { @@ -62,8 +64,8 @@ function rebuildObjectClass($destdir, $module, $objectname, $newmask, $readdir = return -2; } if (!preg_match('/^(integer|price|sellist|varchar|double|text|html|duration)/', $addfieldentry['type']) - && !preg_match('/^(boolean|real|date|datetime|timestamp)$/', $addfieldentry['type'])) { - setEventMessages($langs->trans('BadValueForType', $objectname), null, 'errors'); + && !preg_match('/^(boolean|smallint|real|date|datetime|timestamp|phone|mail|url|ip|password)$/', $addfieldentry['type'])) { + setEventMessages($langs->trans('BadValueForType', $addfieldentry['type']), null, 'errors'); return -2; } } @@ -217,10 +219,14 @@ function rebuildObjectClass($destdir, $module, $objectname, $newmask, $readdir = dol_mkdir(dirname($pathoffiletoedittarget)); //file_put_contents($pathoffiletoedittmp, $contentclass); - file_put_contents(dol_osencode($pathoffiletoedittarget), $contentclass); - @chmod($pathoffiletoedittarget, octdec($newmask)); + $result = file_put_contents(dol_osencode($pathoffiletoedittarget), $contentclass); + if ($result) { + @chmod($pathoffiletoedittarget, octdec($newmask)); + } else { + $error++; + } - return $object; + return $error ? -1 : $object; } catch (Exception $e) { print $e->getMessage(); return -5; @@ -257,13 +263,33 @@ function rebuildObjectSql($destdir, $module, $objectname, $newmask, $readdir = ' // Edit .sql file if ($moduletype == 'internal') { - $pathoffiletoeditsrc = $readdir.'/../install/mysql/tables/llx_'.strtolower($module).'_'.strtolower($objectname).'.sql'; - $pathoffiletoedittarget = $destdir.'/../install/mysql/tables/llx_'.strtolower($module).'_'.strtolower($objectname).'.sql'.($readdir != $destdir ? '.new' : ''); + $pathoffiletoeditsrc = '/../install/mysql/tables/llx_'.strtolower($module).'_'.strtolower($objectname).'.sql'; + if (! dol_is_file($readdir.$pathoffiletoeditsrc)) { + $pathoffiletoeditsrc = '/../install/mysql/tables/llx_'.strtolower($module).'_'.strtolower($objectname).'-'.strtolower($module).'.sql'; + if (! dol_is_file($readdir.$pathoffiletoeditsrc)) { + $pathoffiletoeditsrc = '/../install/mysql/tables/llx_'.strtolower($module).'-'.strtolower($module).'.sql'; + if (! dol_is_file($readdir.$pathoffiletoeditsrc)) { + $pathoffiletoeditsrc = '/../install/mysql/tables/llx_'.strtolower($module).'.sql'; + } + } + } } else { - $pathoffiletoeditsrc = $readdir.'/sql/llx_'.strtolower($module).'_'.strtolower($objectname).'.sql'; - $pathoffiletoedittarget = $destdir.'/sql/llx_'.strtolower($module).'_'.strtolower($objectname).'.sql'.($readdir != $destdir ? '.new' : ''); + $pathoffiletoeditsrc = '/sql/llx_'.strtolower($module).'_'.strtolower($objectname).'.sql'; + if (! dol_is_file($readdir.$pathoffiletoeditsrc)) { + $pathoffiletoeditsrc = '/sql/llx_'.strtolower($module).'_'.strtolower($objectname).'-'.strtolower($module).'.sql'; + if (! dol_is_file($readdir.$pathoffiletoeditsrc)) { + $pathoffiletoeditsrc = '/sql/llx_'.strtolower($module).'-'.strtolower($module).'.sql'; + if (! dol_is_file($readdir.$pathoffiletoeditsrc)) { + $pathoffiletoeditsrc = '/sql/llx_'.strtolower($module).'.sql'; + } + } + } } + // Complete path to be full path + $pathoffiletoedittarget = $destdir.$pathoffiletoeditsrc.($readdir != $destdir ? '.new' : ''); + $pathoffiletoeditsrc = $readdir.$pathoffiletoeditsrc; + if (!dol_is_file($pathoffiletoeditsrc)) { $langs->load("errors"); setEventMessages($langs->trans("ErrorFileNotFound", $pathoffiletoeditsrc), null, 'errors'); @@ -340,16 +366,13 @@ function rebuildObjectSql($destdir, $module, $objectname, $newmask, $readdir = ' @chmod($pathoffiletoedittarget, octdec($newmask)); } else { $error++; + setEventMessages($langs->trans("ErrorFailToCreateFile", $pathoffiletoedittarget), null, 'errors'); } // Edit .key.sql file - if ($moduletype == 'internal') { - $pathoffiletoeditsrc = $readdir.'/../install/mysql/tables/llx_'.strtolower($module).'_'.strtolower($objectname).'.key.sql'; - $pathoffiletoedittarget = $destdir.'/../install/mysql/tables/llx_'.strtolower($module).'_'.strtolower($objectname).'.key.sql'.($readdir != $destdir ? '.new' : ''); - } else { - $pathoffiletoeditsrc = $destdir.'/sql/llx_'.strtolower($module).'_'.strtolower($objectname).'.key.sql'; - $pathoffiletoedittarget = $destdir.'/sql/llx_'.strtolower($module).'_'.strtolower($objectname).'.key.sql'.($readdir != $destdir ? '.new' : ''); - } + $pathoffiletoeditsrc = preg_replace('/\.sql$/', '.key.sql', $pathoffiletoeditsrc); + $pathoffiletoedittarget = preg_replace('/\.sql$/', '.key.sql', $pathoffiletoedittarget); + $pathoffiletoedittarget = preg_replace('/\.sql.new$/', '.key.sql.new', $pathoffiletoedittarget); $contentsql = file_get_contents(dol_osencode($pathoffiletoeditsrc), 'r'); @@ -378,10 +401,11 @@ function rebuildObjectSql($destdir, $module, $objectname, $newmask, $readdir = ' dol_mkdir(dirname($pathoffiletoedittarget)); $result2 = file_put_contents($pathoffiletoedittarget, $contentsql); - if ($result) { + if ($result2) { @chmod($pathoffiletoedittarget, octdec($newmask)); } else { $error++; + setEventMessages($langs->trans("ErrorFailToCreateFile", $pathoffiletoedittarget), null, 'errors'); } return $error ? -1 : 1; diff --git a/htdocs/core/triggers/interface_50_modNotification_Notification.class.php b/htdocs/core/triggers/interface_50_modNotification_Notification.class.php index 6e4f8cb1563..b4d32860c82 100644 --- a/htdocs/core/triggers/interface_50_modNotification_Notification.class.php +++ b/htdocs/core/triggers/interface_50_modNotification_Notification.class.php @@ -90,7 +90,7 @@ class InterfaceNotification extends DolibarrTriggers */ public function getListOfManagedEvents() { - global $conf; + global $conf, $action; global $hookmanager; @@ -100,6 +100,8 @@ class InterfaceNotification extends DolibarrTriggers } $hookmanager->initHooks(array('notification')); + $parameters = array(); + $object = new stdClass(); $reshook = $hookmanager->executeHooks('notifsupported', $parameters, $object, $action); if (empty($reshook)) { if (!empty($hookmanager->resArray['arrayofnotifsupported'])) { diff --git a/htdocs/cron/admin/cron.php b/htdocs/cron/admin/cron.php index 28078242dc6..ff413a8a1c2 100644 --- a/htdocs/cron/admin/cron.php +++ b/htdocs/cron/admin/cron.php @@ -133,15 +133,16 @@ if (!empty($conf->use_javascript_ajax)) { print "\n".''; } diff --git a/htdocs/datapolicy/class/actions_datapolicy.class.php b/htdocs/datapolicy/class/actions_datapolicy.class.php index 5a27b97b691..6b7e27c67aa 100644 --- a/htdocs/datapolicy/class/actions_datapolicy.class.php +++ b/htdocs/datapolicy/class/actions_datapolicy.class.php @@ -417,17 +417,19 @@ class ActionsDatapolicy } if (GETPOST('socid')) { + /* Removed due to awful harcoded values require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php'; $societe = new Societe($this->db); $societe->fetch(GETPOST('socid')); - if (!in_array($object->forme_juridique_code, array(11, 12, 13, 15, 17, 18, 19, 35, 60, 200, 311, 312, 316, 401, 600, 700, 1005)) && $societe->typent_id != 8) { + if (!empty($object->forme_juridique_code) && !in_array($object->forme_juridique_code, array(11, 12, 13, 15, 17, 18, 19, 35, 60, 200, 311, 312, 316, 401, 600, 700, 1005)) && $societe->typent_id != 8) { require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php'; $jsscript .= ''; } + */ } } elseif ($parameters['currentcontext'] == 'contactcard') { if (GETPOST('action') == 'create' || GETPOST('action') == 'edit') { diff --git a/htdocs/debugbar/class/DataCollector/DolibarrCollector.php b/htdocs/debugbar/class/DataCollector/DolibarrCollector.php index c69ebb9a121..3193fe26176 100644 --- a/htdocs/debugbar/class/DataCollector/DolibarrCollector.php +++ b/htdocs/debugbar/class/DataCollector/DolibarrCollector.php @@ -84,7 +84,7 @@ class DolibarrCollector extends DataCollector implements Renderable, AssetProvid protected function getMailInfo() { global $conf, $langs; - global $dolibarr_mailing_limit_sendbyweb; + global $dolibarr_mailing_limit_sendbyweb, $dolibarr_mailing_limit_sendbycli, $dolibarr_mailing_limit_sendbyday; $info = $langs->trans('Method').': '.getDolGlobalString("MAIN_MAIL_SENDMODE").'
'; $info .= $langs->trans('Server').': '.getDolGlobalString("MAIN_MAIL_SMTP_SERVER").'
'; @@ -94,6 +94,8 @@ class DolibarrCollector extends DataCollector implements Renderable, AssetProvid $info .= $langs->trans('TLS/STARTTLS').': '.getDolGlobalString("MAIN_MAIL_EMAIL_TLS").' / '.getDolGlobalString("MAIN_MAIL_EMAIL_STARTTLS").'
'; $info .= $langs->trans('MAIN_DISABLE_ALL_MAILS').': '.(empty($conf->global->MAIN_DISABLE_ALL_MAILS) ? $langs->trans('No') : $langs->trans('Yes')).'
'; $info .= 'dolibarr_mailing_limit_sendbyweb = '.$dolibarr_mailing_limit_sendbyweb.'
'; + $info .= 'dolibarr_mailing_limit_sendbycli = '.$dolibarr_mailing_limit_sendbycli.'
'; + $info .= 'dolibarr_mailing_limit_sendbyday = '.$dolibarr_mailing_limit_sendbyday.'
'; return $info; } diff --git a/htdocs/filefunc.inc.php b/htdocs/filefunc.inc.php index 89b6640eb4d..ccd85e47810 100644 --- a/htdocs/filefunc.inc.php +++ b/htdocs/filefunc.inc.php @@ -179,6 +179,9 @@ if (empty($dolibarr_mailing_limit_sendbyweb)) { if (empty($dolibarr_mailing_limit_sendbycli)) { $dolibarr_mailing_limit_sendbycli = 0; } +if (empty($dolibarr_mailing_limit_sendbyday)) { + $dolibarr_mailing_limit_sendbyday = 0; +} if (empty($dolibarr_strict_mode)) { $dolibarr_strict_mode = 0; // For debug in php strict mode } diff --git a/htdocs/ftp/index.php b/htdocs/ftp/index.php index 419727b1cca..8b4b7bf31c4 100644 --- a/htdocs/ftp/index.php +++ b/htdocs/ftp/index.php @@ -510,6 +510,7 @@ if (!function_exists('ftp_connect')) { $nboflines = count($contents); $rawlisthasfailed = false; $i = 0; + $nbofentries = 0; while ($i < $nboflines && $i < 1000) { $vals = preg_split('@ +@', utf8_encode($buff[$i]), 9); //$vals=preg_split('@ +@','drwxr-xr-x 2 root root 4096 Aug 30 2008 backup_apollon1',9); @@ -527,6 +528,7 @@ if (!function_exists('ftp_connect')) { // Is it a directory ? $is_directory = 0; + $is_link = 0; if ($file == '..') { $is_directory = 1; } elseif (!$rawlisthasfailed) { @@ -695,6 +697,7 @@ function dol_ftp_connect($ftp_server, $ftp_port, $ftp_user, $ftp_password, $sect $ok = 1; $conn_id = null; + $mesg=""; if (!is_numeric($ftp_port)) { $mesg = $langs->transnoentitiesnoconv("FailedToConnectToFTPServer", $ftp_server, $ftp_port); diff --git a/htdocs/install/check.php b/htdocs/install/check.php index 7e21909bb06..1923204c272 100644 --- a/htdocs/install/check.php +++ b/htdocs/install/check.php @@ -80,8 +80,8 @@ if (!empty($useragent)) { } -// Check PHP version -$arrayphpminversionerror = array(5, 5, 0); +// Check PHP version min +$arrayphpminversionerror = array(5, 6, 0); $arrayphpminversionwarning = array(5, 6, 0); if (versioncompare(versionphparray(), $arrayphpminversionerror) < 0) { // Minimum to use (error if lower) print 'Error '.$langs->trans("ErrorPHPVersionTooLow", versiontostring($arrayphpminversionerror)); @@ -97,6 +97,14 @@ if (empty($force_install_nophpinfo)) { } print "
\n"; +// Check PHP version max +$arrayphpmaxversionwarning = array(8, 1, 0); +if (versioncompare(versionphparray(), $arrayphpmaxversionwarning) > 0 && versioncompare(versionphparray(), $arrayphpmaxversionwarning) < 3) { // Maximum to use (warning if higher) + print 'Error '.$langs->trans("ErrorPHPVersionTooHigh", versiontostring($arrayphpmaxversionwarning)); + $checksok = 1; // 0=error, 1=warning + print "
\n"; +} + // Check PHP support for $_GET and $_POST if (!isset($_GET["testget"]) && !isset($_POST["testpost"])) { // We must keep $_GET and $_POST here diff --git a/htdocs/install/default.css b/htdocs/install/default.css index e7bbe6c7771..79f6d3eb9c1 100644 --- a/htdocs/install/default.css +++ b/htdocs/install/default.css @@ -129,6 +129,10 @@ a.button.runupgrade { padding: 10px; } +tr.title.tablesupport-title { + height: 100px; +} + /* Force values for small screen 570 */ @media only screen and (max-width: 570px) { @@ -464,7 +468,7 @@ table.login.tablesupport .title { } table.tablesupport { - min-height: 250px; + min-height: 300px; border: 1px solid #E0E0E0; background: #FFF; } diff --git a/htdocs/install/inc.php b/htdocs/install/inc.php index 27a3fc01abd..a20c3489866 100644 --- a/htdocs/install/inc.php +++ b/htdocs/install/inc.php @@ -195,6 +195,10 @@ if (preg_match('/install\.lock/i', $_SERVER["SCRIPT_FILENAME"])) { $langs->setDefaultLang('auto'); } $langs->load("install"); + + header("X-Content-Type-Options: nosniff"); + header("X-Frame-Options: SAMEORIGIN"); // Frames allowed only if on same domain (stop some XSS attacks) + print $langs->trans("YouTryInstallDisabledByDirLock"); if (!empty($dolibarr_main_url_root)) { print 'Click on following link, '; @@ -216,6 +220,10 @@ if (@file_exists($lockfile)) { $langs->setDefaultLang('auto'); } $langs->load("install"); + + header("X-Content-Type-Options: nosniff"); + header("X-Frame-Options: SAMEORIGIN"); // Frames allowed only if on same domain (stop some XSS attacks) + print $langs->trans("YouTryInstallDisabledByFileLock"); if (!empty($dolibarr_main_url_root)) { print $langs->trans("ClickOnLinkOrRemoveManualy").'
'; @@ -419,6 +427,7 @@ function pHeader($subtitle, $next, $action = 'set', $param = '', $forcejqueryurl // We force the content charset header("Content-type: text/html; charset=".$conf->file->character_set_client); header("X-Content-Type-Options: nosniff"); + header("X-Frame-Options: SAMEORIGIN"); // Frames allowed only if on same domain (stop some XSS attacks) print ''."\n"; print ''."\n"; diff --git a/htdocs/install/mysql/data/llx_c_socialnetworks.sql b/htdocs/install/mysql/data/llx_c_socialnetworks.sql index 468086291fc..7741f8cdfef 100644 --- a/htdocs/install/mysql/data/llx_c_socialnetworks.sql +++ b/htdocs/install/mysql/data/llx_c_socialnetworks.sql @@ -37,7 +37,7 @@ INSERT INTO llx_c_socialnetworks (entity, code, label, url, icon, active) VALUES INSERT INTO llx_c_socialnetworks (entity, code, label, url, icon, active) VALUES ( 1, 'gifycat', 'Gificat', '{socialid}', '', 0); INSERT INTO llx_c_socialnetworks (entity, code, label, url, icon, active) VALUES ( 1, 'giphy', 'Giphy', '{socialid}', '', 0); INSERT INTO llx_c_socialnetworks (entity, code, label, url, icon, active) VALUES ( 1, 'github', 'GitHub', 'https://www.github.com/{socialid}', '', 0); -INSERT INTO llx_c_socialnetworks (entity, code, label, url, icon, active) VALUES ( 1, 'googleplus', 'GooglePlus', 'https://www.googleplus.com/{socialid}', 'fa-google-plus-g', 0); +INSERT INTO llx_c_socialnetworks (entity, code, label, url, icon, active) VALUES ( 1, 'googleplus', 'GooglePlus', 'https://www.googleplus.com/{socialid}', 'fa-google-plus', 0); INSERT INTO llx_c_socialnetworks (entity, code, label, url, icon, active) VALUES ( 1, 'instagram', 'Instagram', 'https://www.instagram.com/{socialid}', 'fa-instagram', 1); INSERT INTO llx_c_socialnetworks (entity, code, label, url, icon, active) VALUES ( 1, 'linkedin', 'LinkedIn', 'https://www.linkedin.com/{socialid}', 'fa-linkedin', 1); INSERT INTO llx_c_socialnetworks (entity, code, label, url, icon, active) VALUES ( 1, 'mastodon', 'Mastodon', '{socialid}', '', 0); diff --git a/htdocs/install/mysql/tables/llx_product_stock.sql b/htdocs/install/mysql/tables/llx_product_stock.sql index c5a2f4ad005..8132a71cdd3 100644 --- a/htdocs/install/mysql/tables/llx_product_stock.sql +++ b/htdocs/install/mysql/tables/llx_product_stock.sql @@ -16,6 +16,7 @@ -- You should have received a copy of the GNU General Public License -- along with this program. If not, see . -- +-- See also its child table llx_product_batch that contains details per lot -- ============================================================================ create table llx_product_stock diff --git a/htdocs/install/step1.php b/htdocs/install/step1.php index 9613e1a86b5..7235e564275 100644 --- a/htdocs/install/step1.php +++ b/htdocs/install/step1.php @@ -911,6 +911,8 @@ function write_conf_file($conffile) fputs($fp, '$dolibarr_mailing_limit_sendbyweb=\'0\';'); fputs($fp, "\n"); + fputs($fp, '$dolibarr_mailing_limit_sendbycli=\'0\';'); + fputs($fp, "\n"); // Write params to overwrites default lib path fputs($fp, "\n"); diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 07cd5da86a9..5fb4f7527a7 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -2288,3 +2288,4 @@ DoesNotWorkWithAllThemes=Will not work with all themes NoName=No name ShowAdvancedOptions= Show advanced options HideAdvancedoptions= Hide advanced options +CIDLookupURL=The module brings an URL that can be used by an external tool to get the name of a thirdparty or contact from its phone number. URL to use is: diff --git a/htdocs/langs/en_US/install.lang b/htdocs/langs/en_US/install.lang index 32f251707a4..6aee82bacec 100644 --- a/htdocs/langs/en_US/install.lang +++ b/htdocs/langs/en_US/install.lang @@ -24,7 +24,8 @@ ErrorWrongValueForParameter=You may have typed a wrong value for parameter '%s'. ErrorFailedToCreateDatabase=Failed to create database '%s'. ErrorFailedToConnectToDatabase=Failed to connect to database '%s'. ErrorDatabaseVersionTooLow=Database version (%s) too old. Version %s or higher is required. -ErrorPHPVersionTooLow=PHP version too old. Version %s is required. +ErrorPHPVersionTooLow=PHP version too old. Version %s or higher is required. +ErrorPHPVersionTooHigh=PHP version too high. Version %s or lower is required. ErrorConnectedButDatabaseNotFound=Connection to server successful but database '%s' not found. ErrorDatabaseAlreadyExists=Database '%s' already exists. ErrorNoMigrationFilesFoundForParameters=No migration file found for the selected versions diff --git a/htdocs/langs/en_US/mails.lang b/htdocs/langs/en_US/mails.lang index 22fe0696363..b86ec3ebbd8 100644 --- a/htdocs/langs/en_US/mails.lang +++ b/htdocs/langs/en_US/mails.lang @@ -178,3 +178,4 @@ IsAnAnswer=Is an answer of an initial email RecordCreatedByEmailCollector=Record created by the Email Collector %s from email %s DefaultBlacklistMailingStatus=Default value for field '%s' when creating a new contact DefaultStatusEmptyMandatory=Empty but mandatory +WarningLimitSendByDay=WARNING: The setup or contract of your instance limits your number of emails per day to %s. Trying to send more may result in having your instance slow down or suspended. Please contact your support if you need a higher quota. diff --git a/htdocs/langs/en_US/modulebuilder.lang b/htdocs/langs/en_US/modulebuilder.lang index 3e029857a10..0bac9e2c435 100644 --- a/htdocs/langs/en_US/modulebuilder.lang +++ b/htdocs/langs/en_US/modulebuilder.lang @@ -155,3 +155,4 @@ LinkToParentMenu=Parent menu (fk_xxxxmenu) ListOfTabsEntries=List of tab entries TabsDefDesc=Define here the tabs provided by your module TabsDefDescTooltip=The tabs provided by your module/application are defined into the array $this->tabs into the module descriptor file. You can edit manually this file or use the embedded editor. +BadValueForType=Bad value for type %s \ No newline at end of file diff --git a/htdocs/margin/admin/margin.php b/htdocs/margin/admin/margin.php index 94330eb8dc1..b87131a4135 100644 --- a/htdocs/margin/admin/margin.php +++ b/htdocs/margin/admin/margin.php @@ -212,7 +212,7 @@ print ''; print ''; print ''.$langs->trans("MARGIN_METHODE_FOR_DISCOUNT").''; print ''; -print Form::selectarray('MARGIN_METHODE_FOR_DISCOUNT', $methods, $conf->global->MARGIN_METHODE_FOR_DISCOUNT); +print Form::selectarray('MARGIN_METHODE_FOR_DISCOUNT', $methods, getDolGlobalString('MARGIN_METHODE_FOR_DISCOUNT')); print ''; print ''; print ''; @@ -230,7 +230,7 @@ print ''.$langs->trans("AgentContactType").''; print ''; $formcompany = new FormCompany($db); $facture = new Facture($db); -print $formcompany->selectTypeContact($facture, $conf->global->AGENT_CONTACT_TYPE, "AGENT_CONTACT_TYPE", "internal", "code", 1, "maxwidth250"); +print $formcompany->selectTypeContact($facture, getDolGlobalString('AGENT_CONTACT_TYPE'), "AGENT_CONTACT_TYPE", "internal", "code", 1, "maxwidth250"); print ''; print ''; print ''; diff --git a/htdocs/master.inc.php b/htdocs/master.inc.php index aa836842e71..fe4bdf42d79 100644 --- a/htdocs/master.inc.php +++ b/htdocs/master.inc.php @@ -75,8 +75,9 @@ if (defined('TEST_DB_FORCE_TYPE')) { // Set properties specific to conf file $conf->file->main_limit_users = $dolibarr_main_limit_users; -$conf->file->mailing_limit_sendbyweb = $dolibarr_mailing_limit_sendbyweb; -$conf->file->mailing_limit_sendbycli = $dolibarr_mailing_limit_sendbycli; +$conf->file->mailing_limit_sendbyweb = empty($dolibarr_mailing_limit_sendbyweb) ? 0 : $dolibarr_mailing_limit_sendbyweb; +$conf->file->mailing_limit_sendbycli = empty($dolibarr_mailing_limit_sendbycli) ? 0 : $dolibarr_mailing_limit_sendbycli; +$conf->file->mailing_limit_sendbyday = empty($dolibarr_mailing_limit_sendbyday) ? 0 : $dolibarr_mailing_limit_sendbyday; $conf->file->main_authentication = empty($dolibarr_main_authentication) ? '' : $dolibarr_main_authentication; // Identification mode $conf->file->main_force_https = empty($dolibarr_main_force_https) ? '' : $dolibarr_main_force_https; // Force https $conf->file->strict_mode = empty($dolibarr_strict_mode) ? '' : $dolibarr_strict_mode; // Force php strict mode (for debug) diff --git a/htdocs/modulebuilder/admin/setup.php b/htdocs/modulebuilder/admin/setup.php index da2cff7eff4..50c86e38cc0 100644 --- a/htdocs/modulebuilder/admin/setup.php +++ b/htdocs/modulebuilder/admin/setup.php @@ -111,7 +111,7 @@ print '
'; print ''; print ''; -print ''; +print ''; print ''; print "\n"; @@ -134,35 +134,35 @@ if ($conf->global->MAIN_FEATURES_LEVEL >= 2) { print ''; print ''; - print ''; + print ''; print ''; print ''; print ''; - print ''; + print ''; print ''; print ''; print ''; - print ''; + print ''; print ''; print ''; print ''; - print ''; + print ''; print ''; print ''; print ''; - print ''; + print ''; print ''; @@ -170,14 +170,14 @@ if ($conf->global->MAIN_FEATURES_LEVEL >= 2) { } print ''; -print ''; +print ''; print ''; print ''; print ''; -print ''; +print ''; print ''; print ''; print ''; -print ''; +print ''; print '
'.$langs->trans("Key").''.$langs->trans("Parameter").''.$langs->trans("Value").'
'.$langs->trans("UseSpecificEditorName").''.$langs->trans("UseSpecificEditorName").''; print ''; print '
'.$langs->trans("UseSpecificEditorURL").''.$langs->trans("UseSpecificEditorURL").''; print ''; print '
'.$langs->trans("UseSpecificFamily").''.$langs->trans("UseSpecificFamily").''; print ''; print '
'.$langs->trans("UseSpecificAuthor").''.$langs->trans("UseSpecificAuthor").''; print ''; print '
'.$langs->trans("UseSpecificVersion").''.$langs->trans("UseSpecificVersion").''; print ''; print '
'.$langs->trans("UseSpecificReadme").''.$langs->trans("UseSpecificReadme").''; print ''; print '
'.$langs->trans("AsciiToHtmlConverter").''.$langs->trans("AsciiToHtmlConverter").''; print ''; print ' '.$langs->trans("Example").': asciidoc, asciidoctor'; @@ -185,7 +185,7 @@ print '
'.$langs->trans("AsciiToPdfConverter").''.$langs->trans("AsciiToPdfConverter").''; print ''; print ' '.$langs->trans("Example").': asciidoctor-pdf'; diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php index c6dec95481c..29cfb898a2c 100644 --- a/htdocs/modulebuilder/index.php +++ b/htdocs/modulebuilder/index.php @@ -343,10 +343,10 @@ if ($dirins && $action == 'initmodule' && $modulename) { '---Put here your own copyright and developer email---'=>dol_print_date($now, '%Y').' '.$user->getFullName($langs).($user->email ? ' <'.$user->email.'>' : ''), 'Editor name'=>$editorname, 'https://www.example.com'=>$editorurl, - '1.0'=>$version, - 'idpicto'=>(empty($picto)) ? 'generic' : $picto, + '$this->version = \'1.0\''=>'$this->version = \''.$version.'\'', + '$this->picto = \'generic\';'=>(empty($picto)) ? '$this->picto = \'generic\'' : '$this->picto = \''.$picto.'\';', "modulefamily" =>$family, - 500000=>$idmodule + '500000'=>$idmodule ); if (!empty($conf->global->MODULEBUILDER_SPECIFIC_EDITOR_NAME)) { @@ -382,7 +382,6 @@ if ($dirins && $action == 'initmodule' && $modulename) { if (!$error) { setEventMessages('ModuleInitialized', null); $module = $modulename; - $modulename = ''; clearstatcache(true); if (function_exists('opcache_invalidate')) { @@ -1519,9 +1518,10 @@ if ($dirins && $action == 'addproperty' && empty($cancel) && !empty($module) && $error++; }*/ + $moduletype = $listofmodules[strtolower($module)]['moduletype']; + // Edit the class file to write properties if (!$error) { - $moduletype = 'external'; $object = rebuildObjectClass($destdir, $module, $objectname, $newmask, $srcdir, $addfieldentry, $moduletype); if (is_numeric($object) && $object <= 0) { @@ -1531,21 +1531,20 @@ if ($dirins && $action == 'addproperty' && empty($cancel) && !empty($module) && // Edit sql with new properties if (!$error) { - $moduletype = 'external'; - $result = rebuildObjectSql($destdir, $module, $objectname, $newmask, $srcdir, $object, $moduletype); + if ($result <= 0) { $error++; } } if (!$error) { + clearstatcache(true); + setEventMessages($langs->trans('FilesForObjectUpdated', $objectname), null); setEventMessages($langs->trans('WarningDatabaseIsNotUpdated'), null); - clearstatcache(true); - // Make a redirect to reload all data header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=objects&module='.$module.($forceddirread ? '@'.$dirread : '').'&tabobj='.$objectname.'&nocache='.time()); @@ -2115,8 +2114,8 @@ if ($module == 'initmodule') { print ''; print '
'; print ajax_combobox("family"); - print ''.$langs->trans("Picto").' '; - print $form->textwithpicto('', $langs->trans("Example").': generic, globe, ... any font awesome code'); + print ''.$langs->trans("Picto").' '; + print $form->textwithpicto('', $langs->trans("Example").': fa-generic, fa-globe, ... any font awesome code.
Advanced syntax is fa-fakey[_faprefix[_facolor[_fasize]]]'); print '
'; print ''.$langs->trans("Description").'
'; @@ -2269,7 +2268,7 @@ if ($module == 'initmodule') { print '
'; print '
'; - print load_fiche_titre($langs->trans("DescriptorFile"), '', ''); + print load_fiche_titre($form->textwithpicto($langs->trans("DescriptorFile"), $pathtofile), '', ''); if (!empty($moduleobj)) { print '
'; @@ -2347,7 +2346,7 @@ if ($module == 'initmodule') { print '

'; // Readme file - print load_fiche_titre($langs->trans("ReadmeFile"), '', ''); + print load_fiche_titre($form->textwithpicto($langs->trans("ReadmeFile"), $pathtofilereadme), '', ''); print ''; if (dol_is_file($dirread.'/'.$pathtofilereadme)) { @@ -2359,7 +2358,7 @@ if ($module == 'initmodule') { print '

'; // ChangeLog - print load_fiche_titre($langs->trans("ChangeLog"), '', ''); + print load_fiche_titre($form->textwithpicto($langs->trans("ChangeLog"), $pathtochangelog), '', ''); print ''; if (dol_is_file($dirread.'/'.$pathtochangelog)) { @@ -2608,10 +2607,63 @@ if ($module == 'initmodule') { $pathtonote = strtolower($module).'/'.strtolower($tabobj).'_note.php'; $pathtocontact = strtolower($module).'/'.strtolower($tabobj).'_contact.php'; $pathtophpunit = strtolower($module).'/test/phpunit/'.strtolower($tabobj).'Test.php'; - $pathtosql = strtolower($module).'/sql/llx_'.strtolower($module).'_'.strtolower($tabobj).'.sql'; - $pathtosqlextra = strtolower($module).'/sql/llx_'.strtolower($module).'_'.strtolower($tabobj).'_extrafields.sql'; - $pathtosqlkey = strtolower($module).'/sql/llx_'.strtolower($module).'_'.strtolower($tabobj).'.key.sql'; - $pathtosqlextrakey = strtolower($module).'/sql/llx_'.strtolower($module).'_'.strtolower($tabobj).'_extrafields.key.sql'; + + // Try to load object class file + clearstatcache(true); + if (function_exists('opcache_invalidate')) { + opcache_invalidate($dirread.'/'.$pathtoclass, true); // remove the include cache hell ! + } + + if (empty($forceddirread) && empty($dirread)) { + $result = dol_include_once($pathtoclass); + $stringofinclude = "dol_include_once(".$pathtoclass.")"; + } else { + $result = @include_once $dirread.'/'.$pathtoclass; + $stringofinclude = "@include_once ".$dirread.'/'.$pathtoclass; + } + if (class_exists($tabobj)) { + try { + $tmpobjet = @new $tabobj($db); + } catch (Exception $e) { + dol_syslog('Failed to load Constructor of class: '.$e->getMessage(), LOG_WARNING); + } + } else { + print ''.$langs->trans('Failed to find the class '.$tabobj.' despite the '.$stringofinclude).'

'; + } + + // Define path for sql file + $pathtosql = strtolower($module).'/sql/llx_'.strtolower($module).'_'.strtolower($tabobj).'-'.strtolower($module).'.sql'; + $result = dol_buildpath($pathtosql); + if (! dol_is_file($result)) { + $pathtosql = strtolower($module).'/sql/llx_'.strtolower($module).'_'.strtolower($tabobj).'.sql'; + $result = dol_buildpath($pathtosql); + if (! dol_is_file($result)) { + $pathtosql = 'install/mysql/tables/llx_'.strtolower($module).'_'.strtolower($tabobj).'-'.strtolower($module).'.sql'; + $result = dol_buildpath($pathtosql); + if (! dol_is_file($result)) { + $pathtosql = 'install/mysql/tables/llx_'.strtolower($module).'-'.strtolower($module).'.sql'; + $result = dol_buildpath($pathtosql); + if (! dol_is_file($result)) { + $pathtosql = 'install/mysql/tables/llx_'.strtolower($module).'.sql'; + $pathtosqlextra = 'install/mysql/tables/llx_'.strtolower($module).'_extrafields.sql'; + $result = dol_buildpath($pathtosql); + } else { + $pathtosqlextra = 'install/mysql/tables/llx_'.strtolower($module).'_extrafields-'.strtolower($module).'.sql'; + } + } else { + $pathtosqlextra = 'install/mysql/tables/llx_'.strtolower($module).'_'.strtolower($tabobj).'_extrafields-'.strtolower($module).'.sql'; + } + } else { + $pathtosqlextra = strtolower($module).'/sql/llx_'.strtolower($module).'_'.strtolower($tabobj).'_extrafields.sql'; + } + } else { + $pathtosqlextra = strtolower($module).'/sql/llx_'.strtolower($module).'_'.strtolower($tabobj).'_extrafields-'.strtolower($module).'.sql'; + } + $pathtosqlroot = preg_replace('/\/llx_.*$/', '', $pathtosql); + + $pathtosqlkey = preg_replace('/\.sql$/', '.key.sql', $pathtosql); + $pathtosqlextrakey = preg_replace('/\.sql$/', '.key.sql', $pathtosqlextra); + $pathtolib = strtolower($module).'/lib/'.strtolower($module).'.lib.php'; $pathtoobjlib = strtolower($module).'/lib/'.strtolower($module).'_'.strtolower($tabobj).'.lib.php'; $pathtopicto = strtolower($module).'/img/object_'.strtolower($tabobj).'.png'; @@ -2643,6 +2695,10 @@ if ($module == 'initmodule') { $urloflist = dol_buildpath('/'.$pathtolist, 1); $urlofcard = dol_buildpath('/'.$pathtocard, 1); + + + + print '
'; // Main DAO class file print ' '.$langs->trans("ClassFile").' : '.(dol_is_file($realpathtoclass) ? '' : '').preg_replace('/^'.strtolower($module).'\//', '', $pathtoclass).(dol_is_file($realpathtoclass) ? '' : '').''; @@ -2773,24 +2829,6 @@ if ($module == 'initmodule') { print '


'; - clearstatcache(true); - if (function_exists('opcache_invalidate')) { - opcache_invalidate($dirread.'/'.$pathtoclass, true); // remove the include cache hell ! - } - - if (empty($forceddirread) && empty($dirread)) { - $result = dol_include_once($pathtoclass); - } else { - $result = @include_once $dirread.'/'.$pathtoclass; - } - if (class_exists($tabobj)) { - try { - $tmpobjet = @new $tabobj($db); - } catch (Exception $e) { - dol_syslog('Failed to load Constructor of class: '.$e->getMessage(), LOG_WARNING); - } - } - if (!empty($tmpobjet)) { $reflector = new ReflectionClass($tabobj); $reflectorproperties = $reflector->getProperties(); // Can also use get_object_vars @@ -2802,6 +2840,7 @@ if ($module == 'initmodule') { print ''; print ''; print ''; + print ''; print ''; print ''; @@ -2990,8 +3029,8 @@ if ($module == 'initmodule') { print ''; print ''; print ''; - print ''; - print ''; + print ''; + print ''; print ''; } else { print ''; @@ -3123,7 +3162,7 @@ if ($module == 'initmodule') { print ''; } else { - print ''.$langs->trans('Failed to init the object with the new.').''; + print ''.$langs->trans('Failed to init the object with the new '.$tabobj.'($db)').''; } } catch (Exception $e) { print $e->getMessage(); diff --git a/htdocs/modulebuilder/template/langs/en_US/mymodule.lang b/htdocs/modulebuilder/template/langs/en_US/mymodule.lang index ca8aa250748..cc518391c33 100644 --- a/htdocs/modulebuilder/template/langs/en_US/mymodule.lang +++ b/htdocs/modulebuilder/template/langs/en_US/mymodule.lang @@ -44,6 +44,7 @@ MyModuleAboutPage = MyModule about page # # Sample page # +MyModuleArea = Home MyModule MyPageName = My page name # diff --git a/htdocs/partnership/class/api_partnership.class.php b/htdocs/partnership/class/api_partnership.class.php new file mode 100644 index 00000000000..1e1c7ca80fe --- /dev/null +++ b/htdocs/partnership/class/api_partnership.class.php @@ -0,0 +1,394 @@ + + * Copyright (C) 2022 Alice Adminson + * + * 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 . + */ + +use Luracast\Restler\RestException; + +dol_include_once('/partnership/class/partnership.class.php'); + + + +/** + * \file partnership/class/api_partnership.class.php + * \ingroup partnership + * \brief File for API management of partnership. + */ + +/** + * API class for partnership partnership + * + * @access protected + * @class DolibarrApiAccess {@requires user,external} + */ +class PartnershipApi extends DolibarrApi +{ + /** + * @var Partnership $partnership {@type Partnership} + */ + public $partnership; + + /** + * Constructor + * + * @url GET / + * + */ + public function __construct() + { + global $db; + $this->db = $db; + $this->partnership = new Partnership($this->db); + } + + /** + * Get properties of a partnership object + * + * Return an array with partnership informations + * + * @param int $id ID of partnership + * @return array|mixed data without useless information + * + * @url GET partnerships/{id} + * + * @throws RestException 401 Not allowed + * @throws RestException 404 Not found + */ + public function get($id) + { + if (!DolibarrApiAccess::$user->rights->partnership->read) { + throw new RestException(401); + } + + $result = $this->partnership->fetch($id); + if (!$result) { + throw new RestException(404, 'Partnership not found'); + } + + if (!DolibarrApi::_checkAccessToResource('partnership', $this->partnership->id, 'partnership')) { + throw new RestException(401, 'Access to instance id='.$this->partnership->id.' of object not allowed for login '.DolibarrApiAccess::$user->login); + } + + return $this->_cleanObjectDatas($this->partnership); + } + + + /** + * List partnerships + * + * Get a list of partnerships + * + * @param string $sortfield Sort field + * @param string $sortorder Sort order + * @param int $limit Limit for list + * @param int $page Page number + * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.ref:like:'SO-%') and (t.date_creation:<:'20160101')" + * @return array Array of order objects + * + * @throws RestException + * + * @url GET /partnerships/ + */ + public function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $sqlfilters = '') + { + global $db, $conf; + + $obj_ret = array(); + $tmpobject = new Partnership($this->db); + + if (!DolibarrApiAccess::$user->rights->partnership->read) { + throw new RestException(401); + } + + $socid = DolibarrApiAccess::$user->socid ? DolibarrApiAccess::$user->socid : ''; + + $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 ($restrictonsocid && !DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) { + $search_sale = DolibarrApiAccess::$user->id; + } + + $sql = "SELECT t.rowid"; + 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 ($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)"; + + if ($tmpobject->ismultientitymanaged) { + $sql .= ' AND t.entity IN ('.getEntity($tmpobject->element).')'; + } + 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 = ".((int) $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 ($restrictonsocid && $search_sale > 0) { + $sql .= " AND sc.fk_user = ".((int) $search_sale); + } + if ($sqlfilters) { + $errormessage = ''; + if (!DolibarrApi::_checkFilters($sqlfilters, $errormessage)) { + throw new RestException(503, 'Error when validating parameter sqlfilters -> '.$errormessage); + } + $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)'; + $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")"; + } + + $sql .= $this->db->order($sortfield, $sortorder); + if ($limit) { + if ($page < 0) { + $page = 0; + } + $offset = $limit * $page; + + $sql .= $this->db->plimit($limit + 1, $offset); + } + + $result = $this->db->query($sql); + $i = 0; + if ($result) { + $num = $this->db->num_rows($result); + while ($i < $num) { + $obj = $this->db->fetch_object($result); + $tmp_object = new Partnership($this->db); + if ($tmp_object->fetch($obj->rowid)) { + $obj_ret[] = $this->_cleanObjectDatas($tmp_object); + } + $i++; + } + } else { + throw new RestException(503, 'Error when retrieving partnership list: '.$this->db->lasterror()); + } + if (!count($obj_ret)) { + throw new RestException(404, 'No partnership found'); + } + return $obj_ret; + } + + /** + * Create partnership object + * + * @param array $request_data Request datas + * @return int ID of partnership + * + * @throws RestException + * + * @url POST partnerships/ + */ + public function post($request_data = null) + { + if (!DolibarrApiAccess::$user->rights->partnership->write) { + throw new RestException(401); + } + + // Check mandatory fields + $result = $this->_validate($request_data); + + foreach ($request_data as $field => $value) { + $this->partnership->$field = $this->_checkValForAPI($field, $value, $this->partnership); + } + + // Clean data + // $this->partnership->abc = sanitizeVal($this->partnership->abc, 'alphanohtml'); + + if ($this->partnership->create(DolibarrApiAccess::$user)<0) { + throw new RestException(500, "Error creating Partnership", array_merge(array($this->partnership->error), $this->partnership->errors)); + } + return $this->partnership->id; + } + + /** + * Update partnership + * + * @param int $id Id of partnership to update + * @param array $request_data Datas + * @return int + * + * @throws RestException + * + * @url PUT partnerships/{id} + */ + public function put($id, $request_data = null) + { + if (!DolibarrApiAccess::$user->rights->partnership->write) { + throw new RestException(401); + } + + $result = $this->partnership->fetch($id); + if (!$result) { + throw new RestException(404, 'Partnership not found'); + } + + if (!DolibarrApi::_checkAccessToResource('partnership', $this->partnership->id, 'partnership')) { + throw new RestException(401, 'Access to instance id='.$this->partnership->id.' of object not allowed for login '.DolibarrApiAccess::$user->login); + } + + foreach ($request_data as $field => $value) { + if ($field == 'id') { + continue; + } + $this->partnership->$field = $this->_checkValForAPI($field, $value, $this->partnership); + } + + // Clean data + // $this->partnership->abc = sanitizeVal($this->partnership->abc, 'alphanohtml'); + + if ($this->partnership->update(DolibarrApiAccess::$user, false) > 0) { + return $this->get($id); + } else { + throw new RestException(500, $this->partnership->error); + } + } + + /** + * Delete partnership + * + * @param int $id Partnership ID + * @return array + * + * @throws RestException + * + * @url DELETE partnerships/{id} + */ + public function delete($id) + { + if (!DolibarrApiAccess::$user->rights->partnership->delete) { + throw new RestException(401); + } + $result = $this->partnership->fetch($id); + if (!$result) { + throw new RestException(404, 'Partnership not found'); + } + + if (!DolibarrApi::_checkAccessToResource('partnership', $this->partnership->id, 'partnership')) { + throw new RestException(401, 'Access to instance id='.$this->partnership->id.' of object not allowed for login '.DolibarrApiAccess::$user->login); + } + + if (!$this->partnership->delete(DolibarrApiAccess::$user)) { + throw new RestException(500, 'Error when deleting Partnership : '.$this->partnership->error); + } + + return array( + 'success' => array( + 'code' => 200, + 'message' => 'Partnership deleted' + ) + ); + } + + + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore + /** + * Clean sensible object datas + * + * @param Object $object Object to clean + * @return Object Object with cleaned properties + */ + protected function _cleanObjectDatas($object) + { + // phpcs:enable + $object = parent::_cleanObjectDatas($object); + + unset($object->rowid); + unset($object->canvas); + + /*unset($object->name); + unset($object->lastname); + unset($object->firstname); + unset($object->civility_id); + unset($object->statut); + unset($object->state); + unset($object->state_id); + unset($object->state_code); + unset($object->region); + unset($object->region_code); + unset($object->country); + unset($object->country_id); + unset($object->country_code); + unset($object->barcode_type); + unset($object->barcode_type_code); + unset($object->barcode_type_label); + unset($object->barcode_type_coder); + unset($object->total_ht); + unset($object->total_tva); + unset($object->total_localtax1); + unset($object->total_localtax2); + unset($object->total_ttc); + unset($object->fk_account); + unset($object->comments); + unset($object->note); + unset($object->mode_reglement_id); + unset($object->cond_reglement_id); + unset($object->cond_reglement); + unset($object->shipping_method_id); + unset($object->fk_incoterms); + unset($object->label_incoterms); + unset($object->location_incoterms); + */ + + // If object has lines, remove $db property + if (isset($object->lines) && is_array($object->lines) && count($object->lines) > 0) { + $nboflines = count($object->lines); + for ($i = 0; $i < $nboflines; $i++) { + $this->_cleanObjectDatas($object->lines[$i]); + + unset($object->lines[$i]->lines); + unset($object->lines[$i]->note); + } + } + + return $object; + } + + /** + * Validate fields before create or update object + * + * @param array $data Array of data to validate + * @return array + * + * @throws RestException + */ + private function _validate($data) + { + $partnership = array(); + foreach ($this->partnership->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"); + } + $partnership[$field] = $data[$field]; + } + return $partnership; + } +} diff --git a/htdocs/partnership/class/partnership.class.php b/htdocs/partnership/class/partnership.class.php index 85787075f28..38d8c333749 100644 --- a/htdocs/partnership/class/partnership.class.php +++ b/htdocs/partnership/class/partnership.class.php @@ -105,8 +105,8 @@ class Partnership extends CommonObject public $fields=array( 'rowid' => array('type'=>'integer', 'label'=>'TechnicalID', 'enabled'=>'1', 'position'=>1, 'notnull'=>1, 'visible'=>0, 'noteditable'=>'1', 'index'=>1, 'css'=>'left', 'comment'=>"Id"), 'ref' => array('type'=>'varchar(128)', 'label'=>'Ref', 'enabled'=>'1', 'position'=>10, 'notnull'=>1, 'visible'=>4, 'noteditable'=>'1', 'default'=>'(PROV)', 'index'=>1, 'searchall'=>1, 'showoncombobox'=>'1', 'comment'=>"Reference of object"), - 'entity' => array('type' => 'integer', 'label' => 'Entity', 'default' => 1, 'enabled' => 1, 'visible' => -2, 'notnull' => 1, 'position' => 15, 'index' => 1), - 'fk_type' => array('type' => 'integer:PartnershipType:partnership/class/partnership_type.class.php:0:active=1', 'label' => 'Type', 'notnull'=>1, 'enabled' => 1, 'visible' => 1, 'position' => 20), + 'entity' => array('type'=>'integer', 'label'=>'Entity', 'enabled'=>'1', 'position'=>15, 'notnull'=>1, 'visible'=>-2, 'default'=>'1', 'index'=>1,), + 'fk_type' => array('type'=>'integer:PartnershipType:partnership/class/partnership_type.class.php:0:active=1', 'label'=>'Type', 'enabled'=>'1', 'position'=>20, 'notnull'=>1, 'visible'=>1,), 'note_public' => array('type'=>'html', 'label'=>'NotePublic', 'enabled'=>'1', 'position'=>61, 'notnull'=>0, 'visible'=>0,), 'note_private' => array('type'=>'html', 'label'=>'NotePrivate', 'enabled'=>'1', 'position'=>62, 'notnull'=>0, 'visible'=>0,), 'date_creation' => array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>'1', 'position'=>500, 'notnull'=>1, 'visible'=>-2,), @@ -118,38 +118,34 @@ class Partnership extends CommonObject 'model_pdf' => array('type'=>'varchar(255)', 'label'=>'Model pdf', 'enabled'=>'1', 'position'=>1010, 'notnull'=>-1, 'visible'=>0,), 'date_partnership_start' => array('type'=>'date', 'label'=>'DatePartnershipStart', 'enabled'=>'1', 'position'=>52, 'notnull'=>1, 'visible'=>1,), 'date_partnership_end' => array('type'=>'date', 'label'=>'DatePartnershipEnd', 'enabled'=>'1', 'position'=>53, 'notnull'=>0, 'visible'=>1,), - 'status' => array('type'=>'smallint', 'label'=>'Status', 'enabled'=>'1', 'position'=>54, 'notnull'=>0, 'visible'=>2, 'index'=>1, 'arrayofkeyval'=>array('-1'=>'','0'=>'Draft', '1'=>'Accepted', '2'=>'Refused', '9'=>'Terminated'),), - 'url_to_check' => array('type'=>'varchar(255)', 'label'=>'UrlToCheck', 'enabled'=>'1', 'position'=>70, 'notnull'=>0, 'visible'=>-1), + 'status' => array('type'=>'smallint', 'label'=>'Status', 'enabled'=>'1', 'position'=>54, 'notnull'=>0, 'visible'=>2, 'index'=>1, 'arrayofkeyval'=>array('-1'=>'', '0'=>'Draft', '1'=>'Accepted', '2'=>'Refused', '8'=>'Suspended', '9'=>'Terminated'),), + 'url_to_check' => array('type'=>'varchar(255)', 'label'=>'UrlToCheck', 'enabled'=>'1', 'position'=>70, 'notnull'=>0, 'visible'=>-1,), 'count_last_url_check_error' => array('type'=>'integer', 'label'=>'CountLastUrlCheckError', 'enabled'=>'1', 'position'=>71, 'notnull'=>0, 'visible'=>-2, 'default'=>'0',), 'last_check_backlink' => array('type'=>'datetime', 'label'=>'LastCheckBacklink', 'enabled'=>'1', 'position'=>72, 'notnull'=>0, 'visible'=>-2,), 'reason_decline_or_cancel' => array('type'=>'text', 'label'=>'ReasonDeclineOrCancel', 'enabled'=>'1', 'position'=>73, 'notnull'=>0, 'visible'=>-2,), - // fk_member and fk_soc are added into constructor + 'fk_soc' => array('type'=>'integer:Societe:societe/class/societe.class.php:1:status=1 AND entity IN (__SHARED_ENTITIES__)', 'label'=>'ThirdParty', 'picto'=>'company', 'enabled'=>'1', 'position'=>50, 'notnull'=>-1, 'visible'=>1, 'index'=>1, 'css'=>'maxwidth500', 'csslist'=>'tdoverflowmax150',), ); - - /** - * @var int rowid - * @deprecated - * @see $id - */ public $rowid; - - public $fk_soc; // Link to thirdparty - public $fk_member; // Link to member - + public $ref; + public $entity; + public $fk_type; + public $note_public; + public $note_private; + public $date_creation; public $tms; public $fk_user_creat; public $fk_user_modif; - - public $status; + public $last_main_doc; + public $import_key; + public $model_pdf; public $date_partnership_start; public $date_partnership_end; + public $status; + public $url_to_check; public $count_last_url_check_error; public $last_check_backlink; - - /** - * @var string reason_decline_or_cancel - */ public $reason_decline_or_cancel; + public $fk_soc; // END MODULEBUILDER PROPERTIES diff --git a/htdocs/partnership/partnership_card.php b/htdocs/partnership/partnership_card.php index 08164421f60..25f8b286fb5 100644 --- a/htdocs/partnership/partnership_card.php +++ b/htdocs/partnership/partnership_card.php @@ -83,8 +83,8 @@ $managedfor = getDolGlobalString('PARTNERSHIP_IS_MANAGED_FOR', 'thirdparty'); if (empty($conf->partnership->enabled)) accessforbidden(); if (empty($permissiontoread)) accessforbidden(); -if ($object->id > 0 && $object->fk_member > 0 && $managedfor != 'member') accessforbidden(); -if ($object->id > 0 && $object->fk_soc > 0 && $managedfor != 'thirdparty') accessforbidden(); +if ($object->id > 0 && !($object->fk_member > 0) && $managedfor == 'member') accessforbidden(); +if ($object->id > 0 && !($object->fk_soc > 0) && $managedfor == 'thirdparty') accessforbidden(); /* diff --git a/htdocs/product/inventory/class/inventory.class.php b/htdocs/product/inventory/class/inventory.class.php index 7229b14ea28..4dff257e257 100644 --- a/htdocs/product/inventory/class/inventory.class.php +++ b/htdocs/product/inventory/class/inventory.class.php @@ -101,7 +101,7 @@ class Inventory extends CommonObject 'entity' => array('type'=>'integer', 'label'=>'Entity', 'visible'=>0, 'enabled'=>1, 'position'=>20, 'notnull'=>1, 'index'=>1,), 'title' => array('type'=>'varchar(255)', 'label'=>'Label', 'visible'=>1, 'enabled'=>1, 'position'=>25, 'css'=>'minwidth300', 'csslist'=>'tdoverflowmax200'), 'fk_warehouse' => array('type'=>'integer:Entrepot:product/stock/class/entrepot.class.php', 'label'=>'Warehouse', 'visible'=>1, 'enabled'=>1, 'position'=>30, 'index'=>1, 'help'=>'InventoryForASpecificWarehouse', 'picto'=>'stock', 'css'=>'minwidth300 maxwidth500 widthcentpercentminusx', 'csslist'=>'tdoverflowmax200'), - 'fk_product' => array('type'=>'integer:Product:product/class/product.class.php::::0:-1:0::1', 'label'=>'Product', 'visible'=>1, 'enabled'=>1, 'position'=>32, 'index'=>1, 'help'=>'InventoryForASpecificProduct', 'picto'=>'product', 'css'=>'minwidth300 maxwidth500 widthcentpercentminusx', 'csslist'=>'tdoverflowmax200'), + 'fk_product' => array('type'=>'integer:Product:product/class/product.class.php', 'label'=>'Product', 'get_name_url_params' => '0::0:-1:0::1', 'visible'=>1, 'enabled'=>1, 'position'=>32, 'index'=>1, 'help'=>'InventoryForASpecificProduct', 'picto'=>'product', 'css'=>'minwidth300 maxwidth500 widthcentpercentminusx', 'csslist'=>'tdoverflowmax200'), 'date_inventory' => array('type'=>'date', 'label'=>'DateValue', 'visible'=>1, 'enabled'=>'$conf->global->STOCK_INVENTORY_ADD_A_VALUE_DATE', 'position'=>35), // This date is not used so disabled by default. 'date_creation' => array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>1, 'visible'=>-2, 'notnull'=>1, 'position'=>500), 'tms' => array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>1, 'visible'=>-2, 'notnull'=>1, 'position'=>501), diff --git a/htdocs/projet/card.php b/htdocs/projet/card.php index 097d670e8ea..c246b73e816 100644 --- a/htdocs/projet/card.php +++ b/htdocs/projet/card.php @@ -515,6 +515,7 @@ if ($action == 'create' && $user->rights->projet->creer) { print ''; print ''; print ''; + print ''; print ''; print dol_get_fiche_head(); diff --git a/htdocs/projet/tasks/task.php b/htdocs/projet/tasks/task.php index 31fa1547ffc..1a0666d1067 100644 --- a/htdocs/projet/tasks/task.php +++ b/htdocs/projet/tasks/task.php @@ -128,6 +128,28 @@ if ($action == 'update' && !GETPOST("cancel") && $user->rights->projet->creer) { } } +if ($action == 'confirm_clone' && $confirm == 'yes') { + //$clone_contacts = GETPOST('clone_contacts') ? 1 : 0; + $clone_prog = GETPOST('clone_prog') ? 1 : 0; + $clone_time = GETPOST('clone_time') ? 1 : 0; + $clone_affectation = GETPOST('clone_affectation') ? 1 : 0; + $clone_change_dt = GETPOST('clone_change_dt') ? 1 : 0; + $clone_notes = GETPOST('clone_notes') ? 1 : 0; + $clone_file = GETPOST('clone_file') ? 1 : 0; + $result = $object->createFromClone($user, $object->id, $object->fk_project, $object->fk_task_parent, $clone_change_dt, $clone_affectation, $clone_time, $clone_file, $clone_notes, $clone_prog); + if ($result <= 0) { + setEventMessages($object->error, $object->errors, 'errors'); + } else { + // Load new object + $newobject = new Task($db); + $newobject->fetch($result); + $newobject->fetch_optionals(); + $newobject->fetch_thirdparty(); // Load new object + $object = $newobject; + $action = ''; + } +} + if ($action == 'confirm_delete' && $confirm == "yes" && $user->rights->projet->supprimer) { $result = $projectstatic->fetch($object->fk_project); $projectstatic->fetch_thirdparty(); @@ -205,6 +227,7 @@ $help_url = ''; llxHeader('', $title, $help_url); + if ($id > 0 || !empty($ref)) { $res = $object->fetch_optionals(); if (!empty($conf->global->PROJECT_ALLOW_COMMENT_ON_TASK) && method_exists($object, 'fetchComments') && empty($object->comments)) { @@ -385,6 +408,22 @@ if ($id > 0 || !empty($ref)) { //$userAccess = $projectstatic->restrictedProjectArea($user); // We allow task affected to user even if a not allowed project //$arrayofuseridoftask=$object->getListContactId('internal'); + if ($action == 'clone') { + $formquestion = array( + 'text' => $langs->trans("ConfirmClone"), + //array('type' => 'checkbox', 'name' => 'clone_contacts', 'label' => $langs->trans("CloneContacts"), 'value' => true), + array('type' => 'checkbox', 'name' => 'clone_change_dt', 'label' => $langs->trans("CloneChanges"), 'value' => true), + array('type' => 'checkbox', 'name' => 'clone_affectation', 'label' => $langs->trans("CloneAffectation"), 'value' => true), + array('type' => 'checkbox', 'name' => 'clone_prog', 'label' => $langs->trans("CloneProgression"), 'value' => true), + array('type' => 'checkbox', 'name' => 'clone_time', 'label' => $langs->trans("CloneTimes"), 'value' => true), + array('type' => 'checkbox', 'name' => 'clone_file', 'label' => $langs->trans("CloneFile"), 'value' => true), + + ); + + print $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$object->id, $langs->trans("ToClone"), $langs->trans("ConfirmCloneTask"), "confirm_clone", $formquestion, '', 1, 300, 590); + } + + $head = task_prepare_head($object); if ($action == 'edit' && $user->rights->projet->creer) { @@ -628,6 +667,7 @@ if ($id > 0 || !empty($ref)) { // Modify if ($user->rights->projet->creer) { print '
'.$langs->trans('Modify').''; + print ''.$langs->trans('Clone').''; } else { print ''.$langs->trans('Modify').''; } diff --git a/htdocs/asterisk/cidlookup.php b/htdocs/public/clicktodial/cidlookup.php similarity index 71% rename from htdocs/asterisk/cidlookup.php rename to htdocs/public/clicktodial/cidlookup.php index 716057198f8..3ec7024855d 100644 --- a/htdocs/asterisk/cidlookup.php +++ b/htdocs/public/clicktodial/cidlookup.php @@ -16,20 +16,45 @@ */ /** - * \file htdocs/asterisk/cidlookup.php + * \file htdocs/public/clicktodial/cidlookup.php * \brief Script to search companies names based on incoming calls, from caller phone number - * \remarks To use this script, your Asterisk must be compiled with CURL, - * and your dialplan must be something like this: + * \remarks To use this script, your Asterisk must be compiled with CURL, and your dialplan must be something like this: * - * exten => s,1,Set(CALLERID(name)=${CURL(http://IP-DOLIBARR:80/asterisk/cidlookup.php?phone=${CALLERID(num)})}) + * exten => s,1,Set(CALLERID(name)=${CURL(http://IP-DOLIBARR:80/asterisk/cidlookup.php?phone=${CALLERID(num)}&securitykey=SECURITYKEY)}) * * Change IP-DOLIBARR to the IP address of your dolibarr server + * Change SECURITYKEY to the value defined into your setup of module ClickToDial */ +if (!defined('NOTOKENRENEWAL')) { + define('NOTOKENRENEWAL', '1'); // Disables token renewal +} +if (!defined('NOREQUIREMENU')) { + define('NOREQUIREMENU', '1'); +} +if (!defined('NOREQUIREHTML')) { + define('NOREQUIREHTML', '1'); +} +if (!defined('NOREQUIREAJAX')) { + define('NOREQUIREAJAX', '1'); +} +if (!defined('NOLOGIN')) { + define('NOLOGIN', '1'); +} +if (!defined('NOIPCHECK')) { + define('NOIPCHECK', '1'); // Do not check IP defined into conf $dolibarr_main_restrict_ip +} -include '../master.inc.php'; +// So log file will have a suffix +if (!defined('USESUFFIXINLOG')) { + define('USESUFFIXINLOG', '_cidlookup'); +} + +include '../../main.inc.php'; $phone = GETPOST('phone'); +$securitykey = GETPOST('securitykey'); + $notfound = $langs->trans("Unknown"); // Security check @@ -38,12 +63,27 @@ if (empty($conf->clicktodial->enabled)) { exit; } + +/* + * View + */ + +if (empty($securitykey)) { + echo 'Securitykey is required. Check setup of clicktodial module.'; + exit; +} +if ($securitykey != getDolGlobalString('CLICKTODIAL_KEY_FOR_CIDLOOKUP')) { + echo 'Securitykey is wrong.'; + exit; +} + // Check parameters if (empty($phone)) { print "Error: Url must be called with parameter phone=phone to search\n"; exit; } + $sql = "SELECT s.nom as name FROM ".MAIN_DB_PREFIX."societe as s"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."socpeople as sp ON sp.fk_soc = s.rowid"; $sql .= " WHERE s.entity IN (".getEntity('societe').")"; diff --git a/htdocs/public/cron/cron_run_jobs_by_url.php b/htdocs/public/cron/cron_run_jobs_by_url.php index 8aa910a2d4f..fea2a2d7f82 100644 --- a/htdocs/public/cron/cron_run_jobs_by_url.php +++ b/htdocs/public/cron/cron_run_jobs_by_url.php @@ -93,7 +93,7 @@ if (empty($key)) { echo 'Securitykey is required. Check setup of cron jobs module.'; exit; } -if ($key != $conf->global->CRON_KEY) { +if ($key != getDolGlobalString('CRON_KEY')) { echo 'Securitykey is wrong.'; exit; } diff --git a/htdocs/recruitment/class/recruitmentcandidature.class.php b/htdocs/recruitment/class/recruitmentcandidature.class.php index 021ed614a5f..b0a8e9e52a0 100644 --- a/htdocs/recruitment/class/recruitmentcandidature.class.php +++ b/htdocs/recruitment/class/recruitmentcandidature.class.php @@ -127,7 +127,7 @@ class RecruitmentCandidature extends CommonObject //'fk_recruitment_origin' => array('type'=>'integer:CRecruitmentOrigin:recruitment/class/crecruitmentorigin.class.php', 'label'=>'Origin', 'enabled'=>'1', 'position'=>45, 'visible'=>1, 'index'=>1), 'remuneration_requested' => array('type'=>'integer', 'label'=>'RequestedRemuneration', 'enabled'=>'1', 'position'=>80, 'notnull'=>0, 'visible'=>-1,), 'remuneration_proposed' => array('type'=>'integer', 'label'=>'ProposedRemuneration', 'enabled'=>'1', 'position'=>81, 'notnull'=>0, 'visible'=>-1,), - 'description' => array('type'=>'html', 'label'=>'Description', 'enabled'=>'1', 'position'=>500, 'notnull'=>0, 'visible'=>3,), + 'description' => array('type'=>'html', 'label'=>'Description', 'enabled'=>'1', 'position'=>500, 'notnull'=>0, 'visible'=>3, 'cssview'=>'wordbreak'), 'import_key' => array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>'1', 'position'=>1000, 'notnull'=>-1, 'visible'=>-2,), 'model_pdf' => array('type'=>'varchar(255)', 'label'=>'Model pdf', 'enabled'=>'1', 'position'=>1010, 'notnull'=>-1, 'visible'=>0,), 'status' => array('type'=>'smallint', 'label'=>'Status', 'enabled'=>'1', 'position'=>1000, 'notnull'=>1, 'visible'=>1, 'index'=>1, 'default'=>0, 'arrayofkeyval'=>array('0'=>'Draft', '1'=>'Received', '3'=>'ContractProposed', '5'=>'ContractSigned', '8'=>'Refused', '9'=>'Canceled')), diff --git a/htdocs/societe/card.php b/htdocs/societe/card.php index aa784d8639d..c25d1edb37f 100644 --- a/htdocs/societe/card.php +++ b/htdocs/societe/card.php @@ -3035,6 +3035,22 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { print "\n"; } + // Link user (you must create a contact to get a user) + /* + print ''.$langs->trans("DolibarrLogin").''; + if ($object->user_id) { + $dolibarr_user = new User($db); + $result = $dolibarr_user->fetch($object->user_id); + print $dolibarr_user->getLoginUrl(-1); + } else { + //print ''.$langs->trans("NoDolibarrAccess").''; + if (!$object->user_id && $user->rights->user->user->creer) { + print ''.img_picto($langs->trans("CreateDolibarrLogin"), 'add').' '.$langs->trans("CreateDolibarrLogin").''; + } + } + print ''; + */ + // Webservices url/key if (!empty($conf->syncsupplierwebservices->enabled)) { print ''.$langs->trans("WebServiceURL").''.dol_print_url($object->webservices_url).''; diff --git a/htdocs/societe/contact.php b/htdocs/societe/contact.php index a09c9751f1f..4ecfc2a8cf4 100644 --- a/htdocs/societe/contact.php +++ b/htdocs/societe/contact.php @@ -173,7 +173,7 @@ print '
'; if ($action != 'presend') { // Contacts list if (empty($conf->global->SOCIETE_DISABLE_CONTACTS)) { - $result = show_contacts($conf, $langs, $db, $object, $_SERVER["PHP_SELF"].'?socid='.$object->id); + $result = show_contacts($conf, $langs, $db, $object, $_SERVER["PHP_SELF"].'?socid='.$object->id, 1); } } diff --git a/htdocs/societe/paymentmodes.php b/htdocs/societe/paymentmodes.php index c0bff452b9c..a63b91b024b 100644 --- a/htdocs/societe/paymentmodes.php +++ b/htdocs/societe/paymentmodes.php @@ -682,6 +682,7 @@ $title = $langs->trans("ThirdParty"); if (!empty($conf->global->MAIN_HTML_TITLE) && preg_match('/thirdpartynameonly/', $conf->global->MAIN_HTML_TITLE) && $object->name) { $title = $object->name." - ".$langs->trans('PaymentInformation'); } +$help_url = ''; llxHeader('', $title, $help_url); diff --git a/htdocs/societe/societecontact.php b/htdocs/societe/societecontact.php index df10c0d4bf9..b1e5174820c 100644 --- a/htdocs/societe/societecontact.php +++ b/htdocs/societe/societecontact.php @@ -128,17 +128,10 @@ $contactstatic = new Contact($db); $userstatic = new User($db); -/* *************************************************************************** */ -/* */ -/* Mode vue et edition */ -/* */ -/* *************************************************************************** */ +// View and edit if ($id > 0 || !empty($ref)) { if ($object->fetch($id, $ref) > 0) { - $soc = new Societe($db); - $soc->fetch($object->socid); - $head = societe_prepare_head($object); print dol_get_fiche_head($head, 'contact', $langs->trans("ThirdParty"), -1, 'company'); diff --git a/htdocs/stripe/class/stripe.class.php b/htdocs/stripe/class/stripe.class.php index b14ed0e8ca6..00d3c4a0d94 100644 --- a/htdocs/stripe/class/stripe.class.php +++ b/htdocs/stripe/class/stripe.class.php @@ -115,7 +115,7 @@ class Stripe extends CommonObject $tokenstring = $obj->tokenstring; $tmparray = json_decode($tokenstring); - $key = $tmparray->stripe_user_id; + $key = empty($tmparray->stripe_user_id) ? '' : $tmparray->stripe_user_id; } else { $tokenstring = ''; } diff --git a/htdocs/support/inc.php b/htdocs/support/inc.php index d5c92cade7b..e6f2afd504d 100644 --- a/htdocs/support/inc.php +++ b/htdocs/support/inc.php @@ -236,6 +236,7 @@ function pHeader($soutitre, $next, $action = 'none') // On force contenu dans format sortie header("Content-type: text/html; charset=".$conf->file->character_set_client); header("X-Content-Type-Options: nosniff"); + header("X-Frame-Options: SAMEORIGIN"); // Frames allowed only if on same domain (stop some XSS attacks) print ''."\n"; print ''."\n"; diff --git a/htdocs/support/index.php b/htdocs/support/index.php index 7330c034aa7..e61fef41f23 100644 --- a/htdocs/support/index.php +++ b/htdocs/support/index.php @@ -77,17 +77,22 @@ print '
'; -print ''; +print ''; +print ''; print ''; print ''; @@ -141,17 +148,22 @@ print "\n"; print '
'; // EMail support -print '
'; -print ''; +print ''; +print ''; print '