';
+
/*if ($conf->global->MAIN_FEATURES_LEVEL >= 2)
{
// Show logo for module
diff --git a/htdocs/categories/index.php b/htdocs/categories/index.php
index f4456ed79bf..4a9e771416c 100644
--- a/htdocs/categories/index.php
+++ b/htdocs/categories/index.php
@@ -102,7 +102,8 @@ if (empty($nosearch)) {
print '
'.$langs->trans("Search").'
';
print '';
print '
';
- print $langs->trans("Name").':
';
+ print $langs->trans("Name").':
';
+ print '
';
print '';
diff --git a/htdocs/comm/action/class/actioncomm.class.php b/htdocs/comm/action/class/actioncomm.class.php
index 9d122cfce7e..f22cea8d04e 100644
--- a/htdocs/comm/action/class/actioncomm.class.php
+++ b/htdocs/comm/action/class/actioncomm.class.php
@@ -1598,7 +1598,7 @@ class ActionComm extends CommonObject
//$tooltip .= ' '.img_picto('', 'email').' '.$langs->trans("Email").'';
$tooltip .= ' '.$langs->trans('MailTopic').': '.$this->email_subject;
$tooltip .= ' '.$langs->trans('MailFrom').': '.str_replace(array('<', '>'), array('<', '>'), $this->email_from);
- $tooltip .= ' '.$langs->trans('MailTo').':, '.str_replace(array('<', '>'), array('<', '>'), $this->email_to);
+ $tooltip .= ' '.$langs->trans('MailTo').': '.str_replace(array('<', '>'), array('<', '>'), $this->email_to);
if (!empty($this->email_tocc)) {
$tooltip .= ' '.$langs->trans('MailCC').': '.str_replace(array('<', '>'), array('<', '>'), $this->email_tocc);
}
diff --git a/htdocs/compta/bank/line.php b/htdocs/compta/bank/line.php
index 033ad7ef30e..3cde5212e2d 100644
--- a/htdocs/compta/bank/line.php
+++ b/htdocs/compta/bank/line.php
@@ -127,7 +127,7 @@ if ($user->rights->banque->modifier && $action == "update") {
$acline = new AccountLine($db);
$result = $acline->fetch($rowid);
if ($result <= 0) {
- dol_syslog('Failed to read bank line with id '.$rowid, LOG_ERR); // This happens due to old bug that has set fk_account to null.
+ dol_syslog('Failed to read bank line with id '.$rowid, LOG_WARNING); // This happens due to old bug that has set fk_account to null.
$acline->id = $rowid;
}
@@ -334,11 +334,12 @@ if ($result) {
// Bank account
print '
'.$langs->trans("Account").'
';
print '
';
- if (!$objp->rappro && !$bankline->getVentilExportCompta()) {
+ // $objp->fk_account may be not > 0 if data was lost by an old bug. In such a case, we let a chance to user to fix it.
+ if (($objp->rappro || $bankline->getVentilExportCompta()) && $objp->fk_account > 0) {
+ print $acct->getNomUrl(1, 'transactions', 'reflabel');
+ } else {
print img_picto('', 'bank_account', 'class="paddingright"');
print $form->select_comptes($acct->id, 'accountid', 0, '', ($acct->id > 0 ? $acct->id : 1), '', 0, '', 1);
- } else {
- print $acct->getNomUrl(1, 'transactions', 'reflabel');
}
print '
\n";
$i++;
}
- $db->free();
+ $db->free($resql);
print "";
} else {
@@ -532,7 +537,8 @@ if ($resql) {
print "\n";
$i++;
}
- $db->free();
+
+ $db->free($resql);
print "";
} else {
@@ -614,7 +620,7 @@ if ($resql) {
print "\n";
$i++;
}
- $db->free();
+ $db->free($resql);
print "";
} else {
diff --git a/htdocs/core/actions_addupdatedelete.inc.php b/htdocs/core/actions_addupdatedelete.inc.php
index f97d4aa94ee..cec127eeac4 100644
--- a/htdocs/core/actions_addupdatedelete.inc.php
+++ b/htdocs/core/actions_addupdatedelete.inc.php
@@ -121,7 +121,7 @@ if ($action == 'add' && !empty($permissiontoadd)) {
// Fill array 'array_options' with data from add form
if (!$error) {
- $ret = $extrafields->setOptionalsFromPost(null, $object);
+ $ret = $extrafields->setOptionalsFromPost(null, $object, '', 1);
if ($ret < 0) {
$error++;
}
diff --git a/htdocs/core/boxes/box_boms.php b/htdocs/core/boxes/box_boms.php
index d96fac8bc76..a9a4f8746da 100644
--- a/htdocs/core/boxes/box_boms.php
+++ b/htdocs/core/boxes/box_boms.php
@@ -147,7 +147,7 @@ class box_boms extends ModeleBoxes
}
$this->info_box_contents[$line][] = array(
- 'td' => 'class="right"',
+ 'td' => 'class="center nowraponall" title="'.dol_escape_htmltag($langs->trans("DateModification").': '.dol_print_date($datem, 'dayhour', 'tzuserrel')).'"',
'text' => dol_print_date($datem, 'day', 'tzuserrel'),
);
diff --git a/htdocs/core/boxes/box_clients.php b/htdocs/core/boxes/box_clients.php
index 2afa630860b..4a7ea965006 100644
--- a/htdocs/core/boxes/box_clients.php
+++ b/htdocs/core/boxes/box_clients.php
@@ -140,7 +140,7 @@ class box_clients extends ModeleBoxes
);
$this->info_box_contents[$line][] = array(
- 'td' => 'class="center nowraponall"',
+ 'td' => 'class="center nowraponall" title="'.dol_escape_htmltag($langs->trans("DateModification").': '.dol_print_date($datem, 'dayhour', 'tzuserrel')).'"',
'text' => dol_print_date($datem, "day", 'tzuserrel')
);
diff --git a/htdocs/core/boxes/box_contacts.php b/htdocs/core/boxes/box_contacts.php
index b2ba608d689..ea35a080d0e 100644
--- a/htdocs/core/boxes/box_contacts.php
+++ b/htdocs/core/boxes/box_contacts.php
@@ -177,7 +177,7 @@ class box_contacts extends ModeleBoxes
);
$this->info_box_contents[$line][] = array(
- 'td' => 'class="right"',
+ 'td' => 'class="center nowraponall" title="'.dol_escape_htmltag($langs->trans("DateModification").': '.dol_print_date($datem, 'dayhour', 'tzuserrel')).'"',
'text' => dol_print_date($datem, "day", 'tzuserrel'),
);
diff --git a/htdocs/core/boxes/box_contracts.php b/htdocs/core/boxes/box_contracts.php
index 8eeb1b93323..dddafffdc02 100644
--- a/htdocs/core/boxes/box_contracts.php
+++ b/htdocs/core/boxes/box_contracts.php
@@ -83,8 +83,8 @@ class box_contracts extends ModeleBoxes
$thirdpartytmp = new Societe($this->db);
$sql = "SELECT s.nom as name, s.rowid as socid, s.email, s.client, s.fournisseur, s.code_client, s.code_fournisseur, s.code_compta, s.code_compta_fournisseur,";
- $sql .= " c.rowid, c.ref, c.statut as fk_statut, c.date_contrat, c.datec, c.fin_validite, c.date_cloture";
- $sql .= ", c.ref_customer, c.ref_supplier";
+ $sql .= " c.rowid, c.ref, c.statut as fk_statut, c.date_contrat, c.datec, c.tms as date_modification, c.fin_validite, c.date_cloture,";
+ $sql .= " c.ref_customer, c.ref_supplier";
$sql .= " FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."contrat as c";
if (empty($user->rights->societe->client->voir) && !$user->socid) {
$sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc";
@@ -117,6 +117,7 @@ class box_contracts extends ModeleBoxes
$objp = $this->db->fetch_object($resql);
$datec = $this->db->jdate($objp->datec);
+ $datem = $this->db->jdate($objp->date_modification);
$dateterm = $this->db->jdate($objp->fin_validite);
$dateclose = $this->db->jdate($objp->date_cloture);
$late = '';
@@ -155,8 +156,8 @@ class box_contracts extends ModeleBoxes
);
$this->info_box_contents[$line][] = array(
- 'td' => 'class="right"',
- 'text' => dol_print_date($datec, 'day', 'tzuserrel'),
+ 'td' => 'class="center nowraponall" title="'.dol_escape_htmltag($langs->trans("DateModification").': '.dol_print_date($datem, 'dayhour', 'tzuserrel')).'"',
+ 'text' => dol_print_date($datem, 'day', 'tzuserrel'),
);
$this->info_box_contents[$line][] = array(
diff --git a/htdocs/core/boxes/box_members.php b/htdocs/core/boxes/box_members.php
index 5865cba2530..e091d58643b 100644
--- a/htdocs/core/boxes/box_members.php
+++ b/htdocs/core/boxes/box_members.php
@@ -145,7 +145,7 @@ class box_members extends ModeleBoxes
);
$this->info_box_contents[$line][] = array(
- 'td' => 'class="center nowraponall"',
+ 'td' => 'class="center nowraponall" title="'.dol_escape_htmltag($langs->trans("DateModification").': '.dol_print_date($datem, 'dayhour', 'tzuserrel')).'"',
'text' => dol_print_date($datem, "day", 'tzuserrel'),
);
diff --git a/htdocs/core/boxes/box_mos.php b/htdocs/core/boxes/box_mos.php
index 6436fb8e34e..cff19388c17 100644
--- a/htdocs/core/boxes/box_mos.php
+++ b/htdocs/core/boxes/box_mos.php
@@ -144,7 +144,7 @@ class box_mos extends ModeleBoxes
}
$this->info_box_contents[$line][] = array(
- 'td' => 'class="center nowraponall"',
+ 'td' => 'class="center nowraponall" title="'.dol_escape_htmltag($langs->trans("DateModification").': '.dol_print_date($datem, 'dayhour', 'tzuserrel')).'"',
'text' => dol_print_date($datem, 'day', 'tzuserrel'),
);
diff --git a/htdocs/core/boxes/box_propales.php b/htdocs/core/boxes/box_propales.php
index f3f9496325f..97b7bd5fd51 100644
--- a/htdocs/core/boxes/box_propales.php
+++ b/htdocs/core/boxes/box_propales.php
@@ -165,7 +165,7 @@ class box_propales extends ModeleBoxes
);
$this->info_box_contents[$line][] = array(
- 'td' => 'class="center nowraponall"',
+ 'td' => 'class="center nowraponall" title="'.dol_escape_htmltag($langs->trans("Date").': '.dol_print_date($datem, 'day', 'tzuserrel')).'"',
'text' => dol_print_date($date, 'day', 'tzuserrel'),
);
diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php
index e1ed8855378..6466754f241 100644
--- a/htdocs/core/class/commonobject.class.php
+++ b/htdocs/core/class/commonobject.class.php
@@ -7805,7 +7805,7 @@ abstract class CommonObject
* @param string $keyprefix Prefix string to add before name and id of field (can be used to avoid duplicate names)
* @param string $onetrtd All fields in same tr td. Used by objectline_create.tpl.php for example.
* @param string $display_type "card" for form display, "line" for document line display (extrafields on propal line, order line, etc...)
- * @return string
+ * @return string String with html content to show
*/
public function showOptionals($extrafields, $mode = 'view', $params = null, $keysuffix = '', $keyprefix = '', $onetrtd = 0, $display_type = 'card')
{
@@ -7814,13 +7814,20 @@ abstract class CommonObject
if (!is_object($form)) {
$form = new Form($db);
}
+ if (!is_object($extrafields)) {
+ dol_syslog('Bad parameter extrafields for showOptionals', LOG_ERR);
+ return 'Bad parameter extrafields for showOptionals';
+ }
+ if (!is_array($extrafields->attributes[$this->table_element])) {
+ dol_syslog("extrafields->attributes was not loaded with extrafields->fetch_name_optionals_label(table_element);", LOG_WARNING);
+ }
$out = '';
$parameters = array();
$reshook = $hookmanager->executeHooks('showOptionals', $parameters, $this, $action); // Note that $action and $object may have been modified by hook
if (empty($reshook)) {
- if (key_exists('label', $extrafields->attributes[$this->table_element]) && is_array($extrafields->attributes[$this->table_element]['label']) && count($extrafields->attributes[$this->table_element]['label']) > 0) {
+ if (is_array($extrafields->attributes[$this->table_element]) && key_exists('label', $extrafields->attributes[$this->table_element]) && is_array($extrafields->attributes[$this->table_element]['label']) && count($extrafields->attributes[$this->table_element]['label']) > 0) {
$out .= "\n";
$out .= ' ';
$out .= "\n";
diff --git a/htdocs/core/class/doleditor.class.php b/htdocs/core/class/doleditor.class.php
index 23c04a98a81..2be0c36c56c 100644
--- a/htdocs/core/class/doleditor.class.php
+++ b/htdocs/core/class/doleditor.class.php
@@ -170,6 +170,9 @@ class DolEditor
if (empty($conf->global->FCKEDITOR_ENABLE_WSC)) { // spellchecker has end of life december 2021
$pluginstodisable .= ',wsc';
}
+ if (empty($conf->global->FCKEDITOR_ENABLE_PDF)) {
+ $pluginstodisable .= ',exportpdf';
+ }
$scaytautostartup = '';
if (!empty($conf->global->FCKEDITOR_ENABLE_SCAYT_AUTOSTARTUP)) {
$scaytautostartup = 'scayt_autoStartup: true,';
@@ -189,14 +192,14 @@ class DolEditor
tmpeditor = CKEDITOR.replace(\''.$this->htmlname.'\',
{
/* property:xxx is same than CKEDITOR.config.property = xxx */
- customConfig : ckeditorConfig,
- removePlugins : \''.$pluginstodisable.'\',
- readOnly : '.($this->readonly ? 'true' : 'false').',
- htmlEncodeOutput :'.$htmlencode_force.',
- allowedContent :'.($disallowAnyContent ? 'false' : 'true').', /* Advanced Content Filter (ACF) is own when allowedContent is false */
- extraAllowedContent : \'a[target];div{float,display}\', /* Add the style float and display into div to default other allowed tags */
- disallowedContent : '.($disallowAnyContent ? '\'\'' : '\'\'').', /* Tags that are not allowed */
- fullPage : '.($fullpage ? 'true' : 'false').', /* if true, the html, header and body tags are kept */
+ customConfig: ckeditorConfig,
+ removePlugins: \''.$pluginstodisable.'\',
+ readOnly: '.($this->readonly ? 'true' : 'false').',
+ htmlEncodeOutput:'.$htmlencode_force.',
+ allowedContent:'.($disallowAnyContent ? 'false' : 'true').', /* Advanced Content Filter (ACF) is own when allowedContent is false */
+ extraAllowedContent: \'a[target];div{float,display}\', /* Add the style float and display into div to default other allowed tags */
+ disallowedContent: '.($disallowAnyContent ? '\'\'' : '\'\'').', /* Tags that are not allowed */
+ fullPage: '.($fullpage ? 'true' : 'false').', /* if true, the html, header and body tags are kept */
toolbar: \''.$this->toolbarname.'\',
toolbarStartupExpanded: '.($this->toolbarstartexpanded ? 'true' : 'false').',
width: '.($this->width ? '\''.$this->width.'\'' : '\'\'').',
diff --git a/htdocs/core/class/extrafields.class.php b/htdocs/core/class/extrafields.class.php
index 3a396e365d7..768031467bc 100644
--- a/htdocs/core/class/extrafields.class.php
+++ b/htdocs/core/class/extrafields.class.php
@@ -1948,14 +1948,15 @@ class ExtraFields
/**
* Fill array_options property of object by extrafields value (using for data sent by forms)
*
- * @param array $extralabels Deprecated (old $array of extrafields, now set this to null)
- * @param object $object Object
- * @param string $onlykey Only some keys are filled:
- * 'string' => When we make update of only one extrafield ($action = 'update_extras'), calling page can set this to avoid to have other extrafields being reset.
- * '@GETPOSTISSET' => When we make update of several extrafields ($action = 'update'), calling page can set this to avoid to have fields not into POST being reset.
- * @return int 1 if array_options set, 0 if no value, -1 if error (field required missing for example)
+ * @param array $extralabels Deprecated (old $array of extrafields, now set this to null)
+ * @param object $object Object
+ * @param string $onlykey Only some keys are filled:
+ * 'string' => When we make update of only one extrafield ($action = 'update_extras'), calling page can set this to avoid to have other extrafields being reset.
+ * '@GETPOSTISSET' => When we make update of several extrafields ($action = 'update'), calling page can set this to avoid to have fields not into POST being reset.
+ * @param int $todefaultifmissing 1=Set value to the default value in database if value is mandatory and missing
+ * @return int 1 if array_options set, 0 if no value, -1 if error (field required missing for example)
*/
- public function setOptionalsFromPost($extralabels, &$object, $onlykey = '')
+ public function setOptionalsFromPost($extralabels, &$object, $onlykey = '', $todefaultifmissing = 0)
{
global $_POST, $langs;
@@ -2015,8 +2016,10 @@ class ExtraFields
|| (!is_array($_POST["options_".$key]) && isset($_POST["options_".$key]) && $this->attributes[$object->table_element]['type'][$key] == 'sellist' && $_POST['options_'.$key] == '0')
|| (is_array($_POST["options_".$key]) && empty($_POST["options_".$key]))) {
//print 'ccc'.$value.'-'.$this->attributes[$object->table_element]['required'][$key];
+
+ // Field is not defined. We mark this as a problem. We may fix it later if there is a default value and $todefaultifmissing is set.
$nofillrequired++;
- $error_field_required[] = $langs->transnoentitiesnoconv($value);
+ $error_field_required[$key] = $langs->transnoentitiesnoconv($value);
}
}
@@ -2047,12 +2050,22 @@ class ExtraFields
}
}
+ if (!empty($error_field_required[$key]) && $todefaultifmissing) {
+ // Value is required but we have a default value and we asked to set empty value to the default value
+ if (!empty($this->attributes[$object->table_element]['default']) && !is_null($this->attributes[$object->table_element]['default'][$key])) {
+ $value_key = $this->attributes[$object->table_element]['default'][$key];
+ unset($error_field_required[$key]);
+ $nofillrequired--;
+ }
+ }
+
$object->array_options["options_".$key] = $value_key;
}
if ($nofillrequired) {
$langs->load('errors');
- setEventMessages($langs->trans('ErrorFieldsRequired').' : '.implode(', ', $error_field_required), null, 'errors');
+ $this->error = $langs->trans('ErrorFieldsRequired').' : '.implode(', ', $error_field_required);
+ setEventMessages($this->error, null, 'errors');
return -1;
} else {
return 1;
diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php
index 48a00919d65..c96db183a3f 100644
--- a/htdocs/core/class/html.form.class.php
+++ b/htdocs/core/class/html.form.class.php
@@ -234,7 +234,11 @@ class Form
if (preg_match('/^(string|safehtmlstring|email)/', $typeofdata)) {
$tmp = explode(':', $typeofdata);
$ret .= '';
- } elseif (preg_match('/^(numeric|amount|integer)/', $typeofdata)) {
+ } elseif (preg_match('/^(integer)/', $typeofdata)) {
+ $tmp = explode(':', $typeofdata);
+ $valuetoshow = price2num($editvalue ? $editvalue : $value, 0);
+ $ret .= '';
+ } elseif (preg_match('/^(numeric|amount)/', $typeofdata)) {
$tmp = explode(':', $typeofdata);
$valuetoshow = price2num($editvalue ? $editvalue : $value);
$ret .= '';
@@ -280,6 +284,7 @@ class Form
$ret .= '';
}
+ // Button save-cancel
if (empty($notabletag)) {
$ret .= '
';
}
@@ -1272,7 +1277,7 @@ class Form
}
// mode 1
- $urloption = 'htmlname='.urlencode($htmlname).'&outjson=1&filter='.urlencode($filter).(empty($excludeids) ? '' : '&excludeids='.join(',', $excludeids)).($showtype ? '&showtype='.urlencode($showtype) : '');
+ $urloption = 'htmlname='.urlencode(str_replace('.', '_', $htmlname)).'&outjson=1&filter='.urlencode($filter).(empty($excludeids) ? '' : '&excludeids='.join(',', $excludeids)).($showtype ? '&showtype='.urlencode($showtype) : '');
$out .= ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT.'/societe/ajax/company.php', $urloption, $conf->global->COMPANY_USE_SEARCH_TO_SELECT, 0, $ajaxoptions);
$out .= '';
@@ -1633,7 +1638,7 @@ class Form
* @param int $socid Id ot third party or 0 for all or -1 for empty list
* @param array|int $selected Array of ID of pre-selected contact id
* @param string $htmlname Name of HTML field ('none' for a not editable field)
- * @param int $showempty 0=no empty value, 1=add an empty value, 2=add line 'Internal' (used by user edit), 3=add an empty value only if more than one record into list
+ * @param int|string $showempty 0=no empty value, 1=add an empty value, 2=add line 'Internal' (used by user edit), 3=add an empty value only if more than one record into list
* @param string $exclude List of contacts id to exclude
* @param string $limitto Disable answers that are not id in this array list
* @param integer $showfunction Add function into label
@@ -8917,10 +8922,11 @@ class Form
$addgendertxt .= '';
break;
case 'other':
- $addgendertxt .= '';
+ $addgendertxt .= '';
break;
}
}
+
/*
$addadmin = '';
if (property_exists($object, 'admin')) {
@@ -9062,7 +9068,7 @@ class Form
$ret .= dol_htmlentities($fullname).$addgendertxt.((!empty($object->societe) && $object->societe != $fullname) ? ' ('.dol_htmlentities($object->societe).')' : '');
}
} elseif (in_array($object->element, array('contact', 'user', 'usergroup'))) {
- $ret .= dol_htmlentities($object->getFullName($langs));
+ $ret .= dol_htmlentities($object->getFullName($langs)).$addgendertxt;
} elseif (in_array($object->element, array('action', 'agenda'))) {
$ret .= $object->ref.' '.$object->label;
} elseif (in_array($object->element, array('adherent_type'))) {
diff --git a/htdocs/core/class/html.formmail.class.php b/htdocs/core/class/html.formmail.class.php
index 244da59b5ff..19ea745c8e1 100644
--- a/htdocs/core/class/html.formmail.class.php
+++ b/htdocs/core/class/html.formmail.class.php
@@ -1533,10 +1533,12 @@ class FormMail extends Form
if (!is_object($extrafields)) {
$extrafields = new ExtraFields($this->db);
}
- $extrafields->fetch_name_optionals_label('product', true);
$product = new Product($this->db);
$product->fetch($line->fk_product, '', '', 1);
$product->fetch_optionals();
+
+ $extrafields->fetch_name_optionals_label($product->table_element, true);
+
if (is_array($extrafields->attributes[$product->table_element]['label']) && count($extrafields->attributes[$product->table_element]['label']) > 0) {
foreach ($extrafields->attributes[$product->table_element]['label'] as $key => $label) {
$substit_line['__PRODUCT_EXTRAFIELD_'.strtoupper($key).'__'] = $product->array_options['options_'.$key];
diff --git a/htdocs/core/class/html.formticket.class.php b/htdocs/core/class/html.formticket.class.php
index 331fe542cb4..a7cc3a996b4 100644
--- a/htdocs/core/class/html.formticket.class.php
+++ b/htdocs/core/class/html.formticket.class.php
@@ -127,12 +127,13 @@ class FormTicket
/**
* Show the form to input ticket
*
- * @param int $withdolfichehead With dol_get_fiche_head() and dol_get_fiche_end()
- * @param string $mode Mode ('create' or 'edit')
- * @param int $public 1=If we show the form for the public interface
+ * @param int $withdolfichehead With dol_get_fiche_head() and dol_get_fiche_end()
+ * @param string $mode Mode ('create' or 'edit')
+ * @param int $public 1=If we show the form for the public interface
+ * @param Contact|null $with_contact [=NULL] Contact to link to this ticket if exists
* @return void
*/
- public function showForm($withdolfichehead = 0, $mode = 'edit', $public = 0)
+ public function showForm($withdolfichehead = 0, $mode = 'edit', $public = 0, Contact $with_contact = null)
{
global $conf, $langs, $user, $hookmanager;
@@ -178,10 +179,104 @@ class FormTicket
}
// TITLE
+ $email = GETPOSTISSET('email') ? GETPOST('email', 'alphanohtml') : '';
if ($this->withemail) {
print '
';
- print '';
+ print '';
print '
';
+
+ if ($with_contact) {
+ // contact search and result
+ $html_contact_search = '';
+ $html_contact_search .= '
';
+ print $html_contact_phone;
+
+ // search contact form email
+ $langs->load('errors');
+ print '';
+ }
}
// If ticket created from another object
@@ -325,7 +420,7 @@ class FormTicket
print '';
print '';
print '';
- print ''.img_picto($langs->trans("Refresh"), 'refresh', 'id="captcha_refresh_img"').'';
+ print ''.img_picto($langs->trans("Refresh"), 'refresh', 'id="captcha_refresh_img"').'';
print '';
print '';
}
diff --git a/htdocs/core/lib/ajax.lib.php b/htdocs/core/lib/ajax.lib.php
index e7bea722e0c..3e1af30ddd2 100644
--- a/htdocs/core/lib/ajax.lib.php
+++ b/htdocs/core/lib/ajax.lib.php
@@ -62,6 +62,8 @@ function ajax_autocompleter($selected, $htmlname, $url, $urloption = '', $minLen
$dataforitem = constant('JS_QUERY_AUTOCOMPLETE_ITEM');
}
+ $htmlnamejquery = str_replace('.', '\\\\.', $htmlname);
+
// Input search_htmlname is original field
// Input htmlname is a second input field used when using ajax autocomplete.
$script = '';
@@ -73,21 +75,21 @@ function ajax_autocompleter($selected, $htmlname, $url, $urloption = '', $minLen
var options = '.json_encode($ajaxoptions).'; /* Option of actions to do after keyup, or after select */
/* Remove selected id as soon as we type or delete a char (it means old selection is wrong). Use keyup/down instead of change to avoid loosing the product id. This is needed only for select of predefined product */
- $("input#search_'.$htmlname.'").keydown(function(e) {
+ $("input#search_'.$htmlnamejquery.'").keydown(function(e) {
if (e.keyCode != 9) /* If not "Tab" key */
{
if (e.keyCode == 13) { return false; } /* disable "ENTER" key useful for barcode readers */
console.log("Clear id previously selected for field '.$htmlname.'");
- $("#'.$htmlname.'").val("");
+ $("#'.$htmlnamejquery.'").val("");
}
});
// Check options for secondary actions when keyup
- $("input#search_'.$htmlname.'").keyup(function() {
+ $("input#search_'.$htmlnamejquery.'").keyup(function() {
if ($(this).val().length == 0)
{
- $("#search_'.$htmlname.'").val("");
- $("#'.$htmlname.'").val("").trigger("change");
+ $("#search_'.$htmlnamejquery.'").val("");
+ $("#'.$htmlnamejquery.'").val("").trigger("change");
if (options.option_disabled) {
$("#" + options.option_disabled).removeAttr("disabled");
}
@@ -118,15 +120,15 @@ function ajax_autocompleter($selected, $htmlname, $url, $urloption = '', $minLen
}
});
- $("input#search_'.$htmlname.'").autocomplete({
+ $("input#search_'.$htmlnamejquery.'").autocomplete({
source: function( request, response ) {
- $.get("'.$url.($urloption ? '?'.$urloption : '').'", { '.$htmlname.': request.term }, function(data){
+ $.get("'.$url.($urloption ? '?'.$urloption : '').'", { "'.str_replace('.', '_', $htmlname).'": request.term }, function(data){
if (data != null)
{
response($.map( data, function(item) {
if (autoselect == 1 && data.length == 1) {
- $("#search_'.$htmlname.'").val(item.value);
- $("#'.$htmlname.'").val(item.key).trigger("change");
+ $("#search_'.$htmlnamejquery.'").val(item.value);
+ $("#'.$htmlnamejquery.'").val(item.key).trigger("change");
}
var label = item.label.toString();
var update = {};
@@ -151,12 +153,13 @@ function ajax_autocompleter($selected, $htmlname, $url, $urloption = '', $minLen
description : item.description,
ref_customer: item.ref_customer }
}));
+ } else {
+ console.error("Error: Ajax url '.$url.($urloption ? '?'.$urloption : '').' has returned an empty page. Should be an empty json array.");
}
- else console.error("Error: Ajax url '.$url.($urloption ? '?'.$urloption : '').' has returned an empty page. Should be an empty json array.");
}, "json");
},
dataType: "json",
- minLength: '.$minLength.',
+ minLength: '.((int) $minLength).',
select: function( event, ui ) { // Function ran once new value has been selected into javascript combo
console.log("We will trigger change on input '.$htmlname.' because of the select definition of autocomplete code for input#search_'.$htmlname.'");
console.log("Selected id = "+ui.item.id+" - If this value is null, it means you select a record with key that is null so selection is not effective");
@@ -164,25 +167,25 @@ function ajax_autocompleter($selected, $htmlname, $url, $urloption = '', $minLen
console.log("Propagate before some properties retrieved by ajax into data-xxx properties");
// For supplier price and customer when price by quantity is off
- $("#'.$htmlname.'").attr("data-up", ui.item.price_ht);
- $("#'.$htmlname.'").attr("data-base", ui.item.pricebasetype);
- $("#'.$htmlname.'").attr("data-qty", ui.item.qty);
- $("#'.$htmlname.'").attr("data-discount", ui.item.discount);
- $("#'.$htmlname.'").attr("data-description", ui.item.description);
- $("#'.$htmlname.'").attr("data-ref-customer", ui.item.ref_customer);
+ $("#'.$htmlnamejquery.'").attr("data-up", ui.item.price_ht);
+ $("#'.$htmlnamejquery.'").attr("data-base", ui.item.pricebasetype);
+ $("#'.$htmlnamejquery.'").attr("data-qty", ui.item.qty);
+ $("#'.$htmlnamejquery.'").attr("data-discount", ui.item.discount);
+ $("#'.$htmlnamejquery.'").attr("data-description", ui.item.description);
+ $("#'.$htmlnamejquery.'").attr("data-ref-customer", ui.item.ref_customer);
';
if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY)) {
$script .= '
// For customer price when PRODUIT_CUSTOMER_PRICES_BY_QTY is on
- $("#'.$htmlname.'").attr("data-pbq", ui.item.pbq);
- $("#'.$htmlname.'").attr("data-pbqup", ui.item.price_ht);
- $("#'.$htmlname.'").attr("data-pbqbase", ui.item.pricebasetype);
- $("#'.$htmlname.'").attr("data-pbqqty", ui.item.qty);
- $("#'.$htmlname.'").attr("data-pbqpercent", ui.item.discount);
+ $("#'.$htmlnamejquery.'").attr("data-pbq", ui.item.pbq);
+ $("#'.$htmlnamejquery.'").attr("data-pbqup", ui.item.price_ht);
+ $("#'.$htmlnamejquery.'").attr("data-pbqbase", ui.item.pricebasetype);
+ $("#'.$htmlnamejquery.'").attr("data-pbqqty", ui.item.qty);
+ $("#'.$htmlnamejquery.'").attr("data-pbqpercent", ui.item.discount);
';
}
$script .= '
- $("#'.$htmlname.'").val(ui.item.id).trigger("change"); // Select new value
+ $("#'.$htmlnamejquery.'").val(ui.item.id).trigger("change"); // Select new value
// Disable an element
if (options.option_disabled) {
@@ -236,7 +239,7 @@ function ajax_autocompleter($selected, $htmlname, $url, $urloption = '', $minLen
}
console.log("ajax_autocompleter new value selected, we trigger change also on original component so on field #search_'.$htmlname.'");
- $("#search_'.$htmlname.'").trigger("change"); // We have changed value of the combo select, we must be sure to trigger all js hook binded on this event. This is required to trigger other javascript change method binded on original field by other code.
+ $("#search_'.$htmlnamejquery.'").trigger("change"); // We have changed value of the combo select, we must be sure to trigger all js hook binded on this event. This is required to trigger other javascript change method binded on original field by other code.
}
,delay: 500
}).data("'.$dataforrenderITem.'")._renderItem = function( ul, item ) {
diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php
index 8776381b922..559d2516e0a 100644
--- a/htdocs/core/lib/functions.lib.php
+++ b/htdocs/core/lib/functions.lib.php
@@ -2257,7 +2257,7 @@ function dol_format_address($object, $withcountry = 0, $sep = "\n", $outputlangs
$ret = '';
$countriesusingstate = array('AU', 'CA', 'US', 'IN', 'GB', 'ES', 'UK', 'TR', 'CN'); // See also MAIN_FORCE_STATE_INTO_ADDRESS
- $sep = "\n";
+
// See format of addresses on https://en.wikipedia.org/wiki/Address
// Address
if (empty($mode)) {
@@ -2357,7 +2357,7 @@ function dol_strftime($fmt, $ts = false, $is_gmt = false)
* @param string $tzoutput true or 'gmt' => string is for Greenwich location
* false or 'tzserver' => output string is for local PHP server TZ usage
* 'tzuser' => output string is for user TZ (current browser TZ with current dst) => In a future, we should have same behaviour than 'tzuserrel'
- * 'tzuserrel' => output string is for user TZ (current browser TZ with dst or not, depending on date position) (TODO not implemented yet)
+ * 'tzuserrel' => output string is for user TZ (current browser TZ with dst or not, depending on date position)
* @param Translate $outputlangs Object lang that contains language for text translation.
* @param boolean $encodetooutput false=no convert into output pagecode
* @return string Formated date or '' if time is null
@@ -3788,7 +3788,7 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $
'recent', 'reception', 'recruitmentcandidature', 'recruitmentjobposition', 'resource', 'recurring',
'shapes', 'square', 'stop-circle', 'supplier', 'supplier_proposal', 'supplier_order', 'supplier_invoice',
'timespent', 'title_setup', 'title_accountancy', 'title_bank', 'title_hrm', 'title_agenda',
- 'uncheck', 'user-cog', 'user-injured', 'user-md', 'vat', 'website', 'workstation',
+ 'uncheck', 'user-cog', 'user-injured', 'user-md', 'vat', 'website', 'workstation', 'world', 'private',
'conferenceorbooth', 'eventorganization'
))) {
$fakey = $pictowithouttext;
@@ -3839,7 +3839,7 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $
'title_agenda'=>'calendar-alt',
'uncheck'=>'times', 'uparrow'=>'share', 'vat'=>'money-check-alt', 'vcard'=>'address-card',
'jabber'=>'comment-o',
- 'website'=>'globe-americas', 'workstation'=>'pallet',
+ 'website'=>'globe-americas', 'workstation'=>'pallet', 'world'=>'globe', 'private'=>'user-lock',
'conferenceorbooth'=>'chalkboard-teacher', 'eventorganization'=>'project-diagram'
);
if ($pictowithouttext == 'off') {
@@ -3908,7 +3908,8 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $
'error'=>'pictoerror', 'warning'=>'pictowarning', 'switch_on'=>'font-status4', 'switch_on_red'=>'font-status8',
'holiday'=>'infobox-holiday', 'info'=>'opacityhigh', 'invoice'=>'infobox-commande',
'knowledgemanagement'=>'infobox-contrat rotate90', 'loan'=>'infobox-bank_account',
- 'payment'=>'infobox-bank_account', 'payment_vat'=>'infobox-bank_account', 'poll'=>'infobox-adherent', 'pos'=>'infobox-bank_account', 'project'=>'infobox-project', 'projecttask'=>'infobox-project', 'propal'=>'infobox-propal',
+ 'payment'=>'infobox-bank_account', 'payment_vat'=>'infobox-bank_account', 'poll'=>'infobox-adherent', 'pos'=>'infobox-bank_account', 'project'=>'infobox-project', 'projecttask'=>'infobox-project',
+ 'propal'=>'infobox-propal', 'private'=>'infobox-project',
'reception'=>'flip', 'recruitmentjobposition'=>'infobox-adherent', 'recruitmentcandidature'=>'infobox-adherent',
'resource'=>'infobox-action',
'salary'=>'infobox-bank_account', 'shipment'=>'infobox-commande', 'supplier_invoice'=>'infobox-order_supplier', 'supplier_invoicea'=>'infobox-order_supplier', 'supplier_invoiced'=>'infobox-order_supplier',
@@ -3931,7 +3932,7 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $
//'dolly'=>'#a69944', 'dollyrevert'=>'#a69944',
'lot'=>'#a69944',
'map-marker-alt'=>'#aaa', 'mrp'=>'#a69944', 'product'=>'#a69944', 'service'=>'#a69944', 'inventory'=>'#a69944', 'stock'=>'#a69944', 'movement'=>'#a69944',
- 'other'=>'#ddd',
+ 'other'=>'#ddd', 'world'=>'#986c6a',
'partnership'=>'#6c6aa8', 'playdisabled'=>'#ccc', 'printer'=>'#444', 'projectpub'=>'#986c6a', 'reception'=>'#a69944', 'resize'=>'#444', 'rss'=>'#cba',
//'shipment'=>'#a69944',
'security'=>'#999', 'square'=>'#888', 'stop-circle'=>'#888', 'stats'=>'#444', 'switch_off'=>'#999', 'technic'=>'#999', 'timespent'=>'#555',
diff --git a/htdocs/core/lib/functions2.lib.php b/htdocs/core/lib/functions2.lib.php
index 8c419eec3c9..f80f041730e 100644
--- a/htdocs/core/lib/functions2.lib.php
+++ b/htdocs/core/lib/functions2.lib.php
@@ -2229,6 +2229,11 @@ function dolGetElementUrl($objectid, $objecttype, $withpicto = 0, $option = '')
$classpath = 'product/stock/class';
$classfile = 'entrepot';
$classname = 'Entrepot';
+ } elseif ($objecttype == 'facturerec') {
+ $classpath = 'compta/facture/class';
+ $classfile = 'facture-rec';
+ $classname = 'FactureRec';
+ $module='facture';
}
if (!empty($conf->$module->enabled)) {
diff --git a/htdocs/core/lib/project.lib.php b/htdocs/core/lib/project.lib.php
index 15162c8b273..56aa24a8523 100644
--- a/htdocs/core/lib/project.lib.php
+++ b/htdocs/core/lib/project.lib.php
@@ -509,7 +509,7 @@ function project_admin_prepare_head()
$head[$h][2] = 'attributes_task';
$h++;
- if (getDolGlobalInt('MAIN_FEATURES_LEVEL') >= 2) {
+ if (!empty($conf->global->PROJECT_USE_OPPORTUNITIES)) {
$langs->load("members");
$head[$h][0] = DOL_URL_ROOT.'/projet/admin/website.php';
@@ -2819,7 +2819,7 @@ function getTaskProgressView($task, $label = true, $progressNumber = true, $hide
$out .= ' ';
} else {
// bad
- $out .= '
';
print '';
- // List of filtered fiels
+ // List of filtered fields
if (isset($objexport->array_export_TypeFields[0]) && is_array($objexport->array_export_TypeFields[0])) {
print '
'.$langs->trans("FilteredFields").'
';
$list = '';
if (!empty($array_filtervalue)) {
foreach ($array_filtervalue as $code => $value) {
+ if (preg_match('/^FormSelect:/', $objexport->array_export_TypeFields[0][$code])) {
+ // We discard this filter if it is a FromSelect field with a value of -1.
+ if ($value == -1) {
+ continue;
+ }
+ }
if (isset($objexport->array_export_fields[0][$code])) {
$list .= ($list ? ', ' : '');
if (isset($array_filtervalue[$code]) && preg_match('/^\s*[<>]/', $array_filtervalue[$code])) {
@@ -1015,7 +1021,7 @@ if ($step == 4 && $datatoexport) {
print $form->selectarray('visibility', $arrayvisibility, 'private');
print '';
print '
';
- print '';
+ print '';
print '
';
$tmpuser = new User($db);
@@ -1148,6 +1154,12 @@ if ($step == 5 && $datatoexport) {
$list = '';
if (!empty($array_filtervalue)) {
foreach ($array_filtervalue as $code => $value) {
+ if (preg_match('/^FormSelect:/', $objexport->array_export_TypeFields[0][$code])) {
+ // We discard this filter if it is a FromSelect field with a value of -1.
+ if ($value == -1) {
+ continue;
+ }
+ }
if (isset($objexport->array_export_fields[0][$code])) {
$list .= ($list ? ', ' : '');
if (isset($array_filtervalue[$code]) && preg_match('/^\s*[<>]/', $array_filtervalue[$code])) {
diff --git a/htdocs/fourn/class/fournisseur.commande.class.php b/htdocs/fourn/class/fournisseur.commande.class.php
index 1d26fb5cfab..b08e31381a1 100644
--- a/htdocs/fourn/class/fournisseur.commande.class.php
+++ b/htdocs/fourn/class/fournisseur.commande.class.php
@@ -3523,7 +3523,7 @@ class CommandeFournisseur extends CommonOrder
empty($this->receptions[$obj->rowid]) ? $this->receptions[$obj->rowid] = $obj->qty : $this->receptions[$obj->rowid] += $obj->qty;
$i++;
}
- $this->db->free();
+ $this->db->free($resql);
return $num;
} else {
diff --git a/htdocs/imports/import.php b/htdocs/imports/import.php
index 15d83cfe8e7..c12b5746e82 100644
--- a/htdocs/imports/import.php
+++ b/htdocs/imports/import.php
@@ -352,6 +352,7 @@ if ($step == 1 || !$datatoimport) {
$serialized_array_match_file_to_database = '';
$array_match_file_to_database = array();
$_SESSION["dol_array_match_file_to_database"] = '';
+ $_SESSION["dol_array_match_file_to_database_select"] = '';
$param = '';
if ($excludefirstline) {
@@ -1078,16 +1079,16 @@ if ($step == 4 && $datatoimport) {
}
}
- $height = '24px'; //needs px for css height attribute below
+ $height = '32px'; //needs px for css height attribute below
$i = 0;
$mandatoryfieldshavesource = true;
- print '
';
+ print '
';
foreach ($fieldstarget as $code => $line) {
if ($i == $minpos) {
break;
}
- print '
';
+ print '
';
$entity = (!empty($objimport->array_import_entities[0][$code]) ? $objimport->array_import_entities[0][$code] : $objimport->array_import_icon[0]);
$tablealias = preg_replace('/(\..*)$/i', '', $code);
@@ -1096,7 +1097,8 @@ if ($step == 4 && $datatoimport) {
$entityicon = !empty($entitytoicon[$entity]) ? $entitytoicon[$entity] : $entity; // $entityicon must string name of picto of the field like 'project', 'company', 'contact', 'modulename', ...
$entitylang = $entitytolang[$entity] ? $entitytolang[$entity] : $objimport->array_import_label[0]; // $entitylang must be a translation key to describe object the field is related to, like 'Company', 'Contact', 'MyModyle', ...
- print '
';
} else {
// Print field of source file
- print '
';
+ print '
';
print '
';
// The image must have the class 'boxhandle' beause it's value used in DOM draggable objects to define the area used to catch the full object
//print img_picto($langs->trans("MoveField", $pos), 'grip_title', 'class="boxhandle" style="cursor:move;"');
diff --git a/htdocs/includes/ckeditor/UPGRADE.md b/htdocs/includes/ckeditor/UPGRADE.md
index e35dc6cff39..73d46f6eb74 100644
--- a/htdocs/includes/ckeditor/UPGRADE.md
+++ b/htdocs/includes/ckeditor/UPGRADE.md
@@ -6,4 +6,4 @@ To upgrade ckeditor:
- Choose skin mona-lisa
- Choose all languages
- Download
-- Repalce files and remove dir 'samples'.
\ No newline at end of file
+- Replace files and remove dir 'samples'.
\ No newline at end of file
diff --git a/htdocs/includes/ckeditor/ckeditor/CHANGES.md b/htdocs/includes/ckeditor/ckeditor/CHANGES.md
index 225251b7913..94ecf8517b9 100644
--- a/htdocs/includes/ckeditor/ckeditor/CHANGES.md
+++ b/htdocs/includes/ckeditor/ckeditor/CHANGES.md
@@ -1,71 +1,495 @@
CKEditor 4 Changelog
====================
+## CKEditor 4.18.0
+
+**Security Updates:**
+
+* Fixed an XSS vulnerability in the core module reported by GitHub Security Lab team member [Kevin Backhouse](https://github.com/kevinbackhouse).
+
+ Issue summary: The vulnerability allowed to inject malformed HTML bypassing content sanitization, which could result in executing a JavaScript code. See [CVE-2022-24728](https://github.com/ckeditor/ckeditor4/security/advisories/GHSA-4fc4-4p5g-6w89) for more details.
+
+* Fixed a Regular expression Denial of Service (ReDoS) vulnerability in dialog plugin discovered by the CKEditor 4 team during our regular security audit.
+
+ Issue summary: The vulnerability allowed to abuse a dialog input validator regular expression, which could cause a significant performance drop resulting in a browser tab freeze. See [CVE-2022-24729](https://github.com/ckeditor/ckeditor4/security/advisories/GHSA-f6rf-9m92-x2hh) for more details.
+
+You can read more details in the relevant security advisory and [contact us](security@cksource.com) if you have more questions.
+
+**An upgrade is highly recommended!**
+
+**Highlights:**
+
+[Web Spell Checker](https://webspellchecker.com/) ended support for WebSpellChecker Dialog on December 31st, 2021. This means the plugin is not supported any longer. Therefore, we decided to deprecate and remove the WebSpellChecker Dialog plugin from CKEditor 4 presets.
+
+We strongly encourage everyone to choose one of the other available spellchecking solutions - [Spell Check As You Type (SCAYT)](https://ckeditor.com/cke4/addon/scayt) or [WProofreader](https://ckeditor.com/cke4/addon/wproofreader).
+
+Fixed issues:
+
+* [#5097](https://github.com/ckeditor/ckeditor4/issues/5097): [Chrome] Fixed: Incorrect conversion of points to pixels while using [`CKEDITOR.tools.convertToPx()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_tools.html#method-convertToPx).
+* [#5044](https://github.com/ckeditor/ckeditor4/issues/5044): Fixed: `select` elements with `multiple` attribute had incorrect styling. Thanks to [John R. D'Orazio](https://github.com/JohnRDOrazio)!
+
+Other changes:
+
+* [#5093](https://github.com/ckeditor/ckeditor4/issues/5093): Deprecated and removed WebSpellChecker Dialog from presets.
+* [#5127](https://github.com/ckeditor/ckeditor4/issues/5127): Deprecated the [`CKEDITOR.rnd`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.html#property-rnd) property to discourage using it in a security-sensitive context.
+* [#5087](https://github.com/ckeditor/ckeditor4/issues/5087): Improved the jQuery adapter by replacing a deprecated jQuery API with existing counterparts. Thanks to [Fran Boon](https://github.com/flavour)!
+* [#5128](https://github.com/ckeditor/ckeditor4/issues/5128): Improved the [Emoji](https://ckeditor.com/cke4/addon/emoji) definitions encoding set by the [`config.emoji_emojiListUrl`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-emoji_emojiListUrl) configuration option.
+
+## CKEditor 4.17.2
+
+Fixed issues:
+
+* [#4934](https://github.com/ckeditor/ckeditor4/issues/4934): Fixed: Active focus in dialog tabs is not visible in the High Contrast mode.
+* [#547](https://github.com/ckeditor/ckeditor4/issues/547): Fixed: Dragging and dropping elements like images within a table is no longer available.
+* [#4875](https://github.com/ckeditor/ckeditor4/issues/4875): Fixed: It is not possible to delete multiple selected lists.
+* [#4873](https://github.com/ckeditor/ckeditor4/issues/4873): Fixed: Pasting content from MS Word and Outlook with horizontal lines prevents images from being uploaded.
+* [#4952](https://github.com/ckeditor/ckeditor4/issues/4952): Fixed: Dragging and dropping images within a table cell appends additional elements.
+* [#4761](https://github.com/ckeditor/ckeditor4/issues/4761): Fixed: Some CSS files are missing unique timestamp used to prevent browser to cache static resources between editor releases.
+* [#4987](https://github.com/ckeditor/ckeditor4/issues/4987): Fixed: [Find/Replace](https://ckeditor.com/cke4/addon/find) is not recognizing more than one space character.
+* [#5061](https://github.com/ckeditor/ckeditor4/issues/5061): Fixed: [Find/Replace](https://ckeditor.com/cke4/addon/find) plugin incorrectly handles multiple whitespace during replacing text.
+* [#5004](https://github.com/ckeditor/ckeditor4/issues/5004): Fixed: `MutationObserver` used in [IFrame Editing Area](https://ckeditor.com/cke4/addon/wysiwygarea) plugin causes memory leaks.
+* [#4994](https://github.com/ckeditor/ckeditor4/issues/4994): Fixed: [Easy Image](https://ckeditor.com/cke4/addon/easyimage) plugin caused content pasted from Word to turn into an image.
+
+API changes:
+
+* [#4918](https://github.com/ckeditor/ckeditor4/issues/4918): Explicitly set the [`config.useComputedState`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-useComputedState) default value to `true`. Thanks to [Shabab Karim](https://github.com/shabab477)!
+* [#4761](https://github.com/ckeditor/ckeditor4/issues/4761): The [`CKEDITOR.appendTimestamp()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.html#method-appendTimestamp) function was added.
+* [#4761](https://github.com/ckeditor/ckeditor4/issues/4761): [`CKEDITOR.dom.document#appendStyleSheet()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_dom_document.html#method-appendStyleSheet) and [`CKEDITOR.tools.buildStyleHtml()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_tools.html#method-buildStyleHtml) now use the newly added [`CKEDITOR.appendTimestamp()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.html#method-appendTimestamp) function to correctly handle caching of CSS files.
+
+Other changes:
+
+* [#5014](https://github.com/ckeditor/ckeditor4/issues/5014): Fixed: Toolbar configurator fails when plugin does not define a toolbar group. Thanks to [SuperPat](https://github.com/SuperPat45)!
+
+## CKEditor 4.17.1
+
+**Highlights:**
+
+Due to a regression in CKEeditor 4.17.0 version that was only revealed after the release and affected a limited area of operation, CSS assets loaded via relative links started to point into invalid location when loaded from external resources.
+
+We have therefore decided to immediately release CKEditor 4.17.1 that fixed this problem. If you have already upgraded to v4.17.0, make sure to upgrade to v4.17.1 to avoid this regression.
+
+Fixed issues:
+
+* [#4979](https://github.com/ckeditor/ckeditor4/issues/3757): Fixed: Added cache key in [#4761](https://github.com/ckeditor/ckeditor4/issues/4761) started to breaking relative links for external CSS resources. The fix has been reverted and will be corrected in the next editor version.
+
+## CKEditor 4.17
+
+**Security Updates:**
+
+* Fixed XSS vulnerability in the core module reported by [William Bowling](https://github.com/wbowling).
+
+ Issue summary: The vulnerability allowed to inject malformed comments HTML bypassing content sanitization, which could result in executing JavaScript code. See [CVE-2021-41165](https://github.com/ckeditor/ckeditor4/security/advisories/GHSA-7h26-63m7-qhf2) for more details.
+
+* Fixed XSS vulnerability in the core module reported by [Maurice Dauer](https://twitter.com/laytonctf).
+
+ Issue summary: The vulnerability allowed to inject malformed HTML bypassing content sanitization, which could result in executing JavaScript code. See [CVE-2021-41164](https://github.com/ckeditor/ckeditor4/security/advisories/GHSA-pvmx-g8h5-cprj) for more details.
+
+You can read more details in the relevant security advisory and [contact us](security@cksource.com) if you have more questions.
+
+**An upgrade is highly recommended!**
+
+**Highlights:**
+
+Adobe [ended support of Flash Player](https://www.adobe.com/products/flashplayer/end-of-life.html) on December 31, 2020 and blocked Flash content from running in Flash Player beginning January 12, 2021.
+We have decided to deprecate and remove the [Flash](https://ckeditor.com/cke4/addon/flash) plugin from CKEditor 4 to help protect users' systems and discourage using insecure software.
+
+New Features:
+
+* [#3433](https://github.com/ckeditor/ckeditor4/issues/3433): Marked required fields in dialogs with asterisk (`*`) symbol.
+* [#4374](https://github.com/ckeditor/ckeditor4/issues/4374): Integrated the [Maximize](https://ckeditor.com/cke4/addon/maximize) plugin with browser's History API.
+* [#4461](https://github.com/ckeditor/ckeditor4/issues/4461): Introduced the possibility to delay editor initialization while it is in a detached DOM element.
+* [#4462](https://github.com/ckeditor/ckeditor4/issues/4462): Introduced support for reattaching editor container element to DOM.
+* [#4612](https://github.com/ckeditor/ckeditor4/issues/4612): Allow pasting images as Base64 from [clipboard](https://ckeditor.com/cke4/addon/clipboard) in all browsers except IE.
+* [#4681](https://github.com/ckeditor/ckeditor4/issues/4681): Allow drag and drop images as Base64.
+* [#4750](https://github.com/ckeditor/ckeditor4/issues/4750): Added notification for pasting and dropping unsupported file types into the editor.
+* [#4807](https://github.com/ckeditor/ckeditor4/issues/4807): [Chrome] Improved the performance of pasting large images. Thanks to [FlowIT-JIT](https://github.com/FlowIT-JIT)!
+* [#4850](https://github.com/ckeditor/ckeditor4/issues/4850): Added support for loading [content templates](https://ckeditor.com/cke4/addon/templates) from HTML files. Thanks to [Fynn96](https://github.com/Fynn96)!
+* [#4874](https://github.com/ckeditor/ckeditor4/issues/4874): Added the [`config.clipboard_handleImages`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-clipboard_handleImages) configuration option for enabling and disabling built-in support for pasting and dropping images in the [Clipboard](https://ckeditor.com/cke4/addon/clipboard) plugin. Thanks to [FlowIT-JIT](https://github.com/FlowIT-JIT)!
+* [#4026](https://github.com/ckeditor/ckeditor4/issues/4026): [Preview](https://ckeditor.com/cke4/addon/preview) plugin now uses the [`editor#title`](http://localhost/ckeditor4-docs/build/docs/ckeditor4/latest/api/CKEDITOR_editor.html#property-title) property for the title of the preview window. Thanks to [Ely](https://github.com/Elyasin)!
+* [#4467](https://github.com/ckeditor/ckeditor4/issues/4467): Added support for inserting content next to a block [widgets](https://ckeditor.com/cke4/addon/widget) using keyboard navigation. Thanks to [bunglegrind](https://github.com/bunglegrind)!
+
+Fixed Issues:
+
+* [#3757](https://github.com/ckeditor/ckeditor4/issues/3757): [Firefox] Fixed: images pasted from [clipboard](https://ckeditor.com/cke4/addon/clipboard) are not inserted as Base64-encoded images.
+* [#3876](https://github.com/ckeditor/ckeditor4/issues/3876): Fixed: The [Print](https://ckeditor.com/cke4/addon/print) plugin incorrectly prints links and images.
+* [#4444](https://github.com/ckeditor/ckeditor4/issues/4444): [Firefox] Fixed: Print preview is incorrectly loaded from CDN.
+* [#4596](https://github.com/ckeditor/ckeditor4/issues/4596): Fixed: Incorrect handling of HSL/HSLA values in [`CKEDITOR.tools.color`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_tools_color.html).
+* [#4597](https://github.com/ckeditor/ckeditor4/issues/4597): Fixed: Incorrect color conversion for HSL/HSLA values in [`CKEDITOR.tools.color`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_tools_color.html).
+* [#4604](https://github.com/ckeditor/ckeditor4/issues/4604): Fixed: [`CKEDITOR.plugins.clipboard.dataTransfer#getTypes()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_plugins_clipboard_dataTransfer.html#method-getTypes) returns no types.
+* [#4761](https://github.com/ckeditor/ckeditor4/issues/4761): Fixed: Not all resources loaded by the editor respect the cache key.
+* [#4783](https://github.com/ckeditor/ckeditor4/issues/4783): Fixed: The [Accessibility Help](https://ckeditor.com/cke4/addon/a11yhelp) dialog does not contain info about focus being moved back to the editing area upon activating a toolbar button.
+* [#4790](https://github.com/ckeditor/ckeditor4/issues/4790): Fixed: Printing page is invoked before the printed page is fully loaded.
+* [#4874](https://github.com/ckeditor/ckeditor4/issues/4874): Fixed: Built-in support for pasting and dropping images in the [Clipboard](https://ckeditor.com/cke4/addon/clipboard) plugin restricts third party plugins from handling image pasting. Thanks to [FlowIT-JIT](https://github.com/FlowIT-JIT)!
+* [#4888](https://github.com/ckeditor/ckeditor4/issues/4888): Fixed: The [`CKEDITOR.dialog#setState()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_dialog.html#method-setState) method throws error when there is no "OK" button in the dialog.
+* [#4858](https://github.com/ckeditor/ckeditor4/issues/4858): Fixed: The [Autolink](https://ckeditor.com/cke4/addon/autolink) plugin incorrectly escapes the `&` characters when pasting links into the editor.
+* [#4892](https://github.com/ckeditor/ckeditor4/issues/4892): Fixed: Focus of buttons in dialogs is not visible enough in High Contrast mode.
+* [#3858](https://github.com/ckeditor/ckeditor4/issues/3858): Fixed: Pasting content in `ENTER_BR` [enter mode](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-enterMode) crashes the editor.
+* [#4891](https://github.com/ckeditor/ckeditor4/issues/4891): Fixed: The [Autogrow](https://ckeditor.com/cke4/addon/autogrow) plugin applies fixed width to the editor.
+
+API Changes:
+
+* [#4462](https://github.com/ckeditor/ckeditor4/issues/4462): [`CKEDITOR.editor#getSelection()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#method-getSelection) now returns `null` if the editor is in recreating state.
+* [#4583](https://github.com/ckeditor/ckeditor4/issues/4583): Added support for new, comma-less color syntax to [`CKEDITOR.tools.color`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_tools_color.html).
+* [#4604](https://github.com/ckeditor/ckeditor4/issues/4604): Added the [`CKEDITOR.plugins.clipboard.dataTransfer#isFileTransfer()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_plugins_clipboard_dataTransfer.html#method-isFileTransfer) method.
+* [#4790](https://github.com/ckeditor/ckeditor4/issues/4790): Added `callback` parameter to [`CKEDITOR.plugins.preview#createPreview()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_plugins_preview.html#method-createPreview) method.
+
+Other Changes:
+
+* [#4866](https://github.com/ckeditor/ckeditor4/issues/#4866): The [Flash](https://ckeditor.com/cke4/addon/flash) plugin is now deprecated and has been removed from CKEditor 4.
+* [#4901](https://github.com/ckeditor/ckeditor4/issues/4901): Redesigned buttons placement in the [Content templates](https://ckeditor.com/cke4/addon/templates) dialog to make it more UX friendly. Thanks to [Fynn96](https://github.com/Fynn96)!
+
+## CKEditor 4.16.2
+
+**Security Updates:**
+
+* Fixed XSS vulnerability in the [Clipboard](https://ckeditor.com/cke4/addon/clipboard) plugin reported by [Anton Subbotin](https://github.com/skavans).
+
+ Issue summary: The vulnerability allowed to abuse paste functionality using malformed HTML, which could result in injecting arbitrary HTML into the editor. See [CVE-2021-32809](https://github.com/ckeditor/ckeditor4/security/advisories/GHSA-7889-rm5j-hpgg) for more details.
+
+* Fixed XSS vulnerability in the [Widget](https://ckeditor.com/cke4/addon/widget) plugin reported by [Anton Subbotin](https://github.com/skavans).
+
+ Issue summary: The vulnerability allowed to abuse undo functionality using malformed [Widget](https://ckeditor.com/cke4/addon/widget) HTML, which could result in executing JavaScript code. See [CVE-2021-32808](https://github.com/ckeditor/ckeditor4/security/advisories/GHSA-6226-h7ff-ch6c) for more details.
+
+* Fixed XSS vulnerability in the [Fake Objects](https://ckeditor.com/cke4/addon/fakeobjects) plugin reported by [Mika Kulmala](https://github.com/kulmik).
+
+ Issue summary: The vulnerability allowed to inject malformed [Fake Objects](https://ckeditor.com/cke4/addon/fakeobjects) HTML, which could result in executing JavaScript code. See [CVE-2021-37695](https://github.com/ckeditor/ckeditor4/security/advisories/GHSA-m94c-37g6-cjhc) for more details.
+
+You can read more details in the relevant security advisory and [contact us](security@cksource.com) if you have more questions.
+
+**An upgrade is highly recommended!**
+
+Fixed Issues:
+* [#4777](https://github.com/ckeditor/ckeditor4/issues/4777): Fixed: HTML comments in widgets not processed correctly.
+* [#4733](https://github.com/ckeditor/ckeditor4/pull/4733): Fixed: [Link](https://ckeditor.com/cke4/addon/link) prevent duplicate anchors in text with styles.
+ * [#4728](https://github.com/ckeditor/ckeditor4/issues/4728): Fixed: Multiple anchors in one line and multi-line with text style.
+ * [#3863](https://github.com/ckeditor/ckeditor4/issues/3863): Fixed: Multiple anchors in single word with text style.
+* [#3819](https://github.com/ckeditor/ckeditor4/issues/3819): [Chrome] Fixed: After removing one of the two consecutive spaces, the ` ` character appears in the editor instead of a space.
+* [#4666](https://github.com/ckeditor/ckeditor4/pull/4666): [IE] Introduce CSS.escape polyfill. Thanks to [limingli0707](https://github.com/limingli0707)!
+ * [#681](https://github.com/ckeditor/ckeditor4/issues/681): Fixed: Table elements (td, tr, th, ..) with an id that starts with dot (.) causes javascript runtime err.
+ * [#641](https://github.com/ckeditor/ckeditor4/issues/641): Fixed: UploadImage Plugin Widgets not working in IE, Opera, Safari, PhantomJS.
+* [#3638](https://github.com/ckeditor/ckeditor4/issues/3638): Fixed: Opening the same dialog twice causes it to become hidden under the dialog's page cover.
+* [#4247](https://github.com/ckeditor/ckeditor4/issues/4247): Fixed: [Color Button](https://ckeditor.com/cke4/addon/colorbutton)'s incorrect rendering on the first opening.
+* [#4555](https://github.com/ckeditor/ckeditor4/issues/4555): Fixed: [Font](https://ckeditor.com/cke4/addon/font) styles with attributes are not applied correctly when used multiple times over the same selection.
+* [#4782](https://github.com/ckeditor/ckeditor4/issues/4782): [Firefox] Fixed: `TypeError` is thrown when switching to Source View and back while [Autocomplete](https://ckeditor.com/cke4/addon/autocomplete) plugin is enabled.
+
+## CKEditor 4.16.1
+
+Fixed Issues:
+* [#4617](https://github.com/ckeditor/ckeditor4/issues/4617): Fixed: [Autocomplete](https://ckeditor.com/cke4/addon/autocomplete) is not accessible in inline editors.
+* [#4493](https://github.com/ckeditor/ckeditor4/issues/4493): Fixed: The [drop-down](https://ckeditor.com/cke4/addon/richcombo) label does not reflect the current value of the drop-down.
+* [#1572](https://github.com/ckeditor/ckeditor4/issues/1572): Fixed: A paragraph before or after a [widget](https://ckeditor.com/cke4/addon/widget) cannot be removed. Thanks to [bunglegrind](https://github.com/bunglegrind)!
+* [#4301](https://github.com/ckeditor/ckeditor4/issues/4301): Fixed: Pasted content is overwritten when pasted in an initially empty editor with the [`div` Enter mode](https://ckeditor.com/docs/ckeditor4/latest/features/enterkey.html).
+* [#4351](https://github.com/ckeditor/ckeditor4/issues/4351): Fixed: Incorrect values for RGBA/HSLA colors in [Color Dialog](https://ckeditor.com/cke4/addon/colordialog).
+* [#4509](https://github.com/ckeditor/ckeditor4/issues/4509): Fixed: Incorrect handling of drag & drop inside [widgets](https://ckeditor.com/cke4/addon/widget) and nested editables.
+* [#4611](https://github.com/ckeditor/ckeditor4/issues/4611): [Android, iOS] Fixed: Incorrect hover styles for buttons in the toolbar on mobile devices.
+* [#4652](https://github.com/ckeditor/ckeditor4/issues/4652): Fixed: [Event data](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_eventInfo.html) set to `false` is treated as an event cancellation.
+* [#4659](https://github.com/ckeditor/ckeditor4/issues/4659): Fixed: [`CKEDITOR.htmlParser`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_htmlParser.html) does not treat `--!>` as a comment end tag correctly.
+
+## CKEditor 4.16
+
+**Security Updates:**
+
+* Fixed ReDoS vulnerability in the [Autolink](https://ckeditor.com/cke4/addon/autolink) plugin.
+
+ Issue summary: It was possible to execute a ReDoS-type attack inside CKEditor 4 by persuading a victim to paste a specially crafted URL-like text into the editor and press Enter or Space.
+
+* Fixed ReDoS vulnerability in the [Advanced Tab for Dialogs](https://ckeditor.com/cke4/addon/dialogadvtab) plugin.
+
+ Issue summary: It was possible to execute a ReDoS-type attack inside CKEditor 4 by persuading a victim to paste a specially crafted text into the Styles dialog.
+
+**An upgrade is highly recommended!**
+
+New Features:
+
+* [#2800](https://github.com/ckeditor/ckeditor4/issues/2800): Unsupported image formats are now gracefully handled by the [Paste from Word](https://ckeditor.com/cke4/addon/pastefromword) plugin on paste, additionally showing descriptive error messages.
+* [#2800](https://github.com/ckeditor/ckeditor4/issues/2800): Unsupported image formats are now gracefully handled by the [Paste from LibreOffice](https://ckeditor.com/cke4/addon/pastefromlibreoffice) plugin on paste, additionally showing descriptive error messages.
+* [#3582](https://github.com/ckeditor/ckeditor4/issues/3582): Introduced smart positioning of the [Autocomplete](https://ckeditor.com/cke4/addon/autocomplete) panel used by the [Mentions](https://ckeditor.com/cke4/addon/mentions) and [Emoji](https://ckeditor.com/cke4/addon/emoji) plugins. The panel will now be additionally positioned related to the browser viewport to be always fully visible.
+* [#4388](https://github.com/ckeditor/ckeditor4/issues/4388): Added the option to remove an iframe created with the [IFrame Dialog](https://ckeditor.com/cke4/addon/iframe) plugin from the sequential keyboard navigation using the `tabindex` attribute. Thanks to [Timo Kirkkala](https://github.com/kirkkala)!
+
+Fixed Issues:
+
+* [#1134](https://github.com/ckeditor/ckeditor4/issues/1134): [Safari] Fixed: [Paste from Word](https://ckeditor.com/cke4/addon/pastefromword) does not embed images.
+* [#2800](https://github.com/ckeditor/ckeditor4/issues/2800): Fixed: No images are imported from Microsoft Word when the content is pasted via the [Paste from Word](https://ckeditor.com/cke4/addon/pastefromword) plugin if there is at least one image of unsupported format.
+* [#4379](https://github.com/ckeditor/ckeditor4/issues/4379): [Edge] Fixed: Incorrect detection of the [high contrast mode](https://ckeditor.com/docs/ckeditor4/latest/guide/dev_a11y.html#high-contrast-mode).
+* [#4422](https://github.com/ckeditor/ckeditor4/issues/4422): Fixed: Missing space between the button name and the keyboard shortcut inside the button label in the [high contrast mode](https://ckeditor.com/docs/ckeditor4/latest/guide/dev_a11y.html#high-contrast-mode).
+* [#2208](https://github.com/ckeditor/ckeditor4/issues/2208): [IE] Fixed: The [Autolink](https://ckeditor.com/cke4/addon/autolink) plugin duplicates the native browser implementation.
+* [#1824](https://github.com/ckeditor/ckeditor4/issues/1824): Fixed: The [Autolink](https://ckeditor.com/cke4/addon/autolink) plugin should require the [Link](https://ckeditor.com/cke4/addon/link) plugin.
+* [#4253](https://github.com/ckeditor/ckeditor4/issues/4253): Fixed: The [Editor Placeholder](https://ckeditor.com/cke4/addon/editorplaceholder) plugin throws an error during the editor initialization with [`config.fullPage`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-fullPage) enabled when there is no `` tag in the editor content.
+* [#4372](https://github.com/ckeditor/ckeditor4/issues/4372): Fixed: The [Autogrow](https://ckeditor.com/cke4/addon/autogrow) plugin changes the editor's width when used with an absolute [`config.width`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-width) value.
+
+API Changes:
+
+* [#4358](https://github.com/ckeditor/ckeditor4/issues/4358): Introduced the [`CKEDITOR.tools.color`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_tools_color.html) class which adds colors validation and methods for converting colors between various formats: named colors, HEX, RGB, RGBA, HSL and HSLA.
+* [#3782](https://github.com/ckeditor/ckeditor4/issues/3782): Moved the [`CKEDITOR.plugins.pastetools.filters.word.images`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_plugins_pastetools_filters_word_images.html) filters to the [`CKEDITOR.plugins.pastetools.filters.image`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_plugins_pastetools_filters_image.html) namespace.
+* [#4297](https://github.com/ckeditor/ckeditor4/issues/4297): All [`CKEDITOR.plugins.pastetools.filters`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_plugins_pastetools_filters.html) are now available under the [`CKEDITOR.pasteTools`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.html#property-pasteTools) alias.
+* [#4394](https://github.com/ckeditor/ckeditor4/issues/4394): Introduced [`CKEDITOR.ajax`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_ajax.html) specialized loading methods for loading binary ([`CKEDITOR.ajax.loadBinary()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_ajax.html#method-loadBinary)) and text ([`CKEDITOR.ajax.loadText()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_ajax.html#method-loadText)) data.
+
+Other Changes:
+
+* The [WebSpellChecker](https://ckeditor.com/cke4/addon/wsc) (WSC) plugin is now disabled by default in [Standard and Full presets](https://ckeditor.com/cke4/presets). It can be enabled via [`extraPlugins`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-extraPlugins) configuration option.
+
+## CKEditor 4.15.1
+
+**Security Updates:**
+
+* Fixed XSS vulnerability in the [Color History feature](https://ckeditor.com/docs/ckeditor4/latest/features/colorbutton.html#color-history) reported by [Mark Wade](https://github.com/mark-wade).
+
+ Issue summary: It was possible to execute an XSS-type attack inside CKEditor 4 by persuading a victim to paste a specially crafted HTML code into the [Color Button](https://ckeditor.com/cke4/addon/colorbutton) dialog.
+
+**An upgrade is highly recommended!**
+
+Fixed Issues:
+
+* [#4293](https://github.com/ckeditor/ckeditor4/issues/4293): Fixed: The [`CKEDITOR.inlineAll()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.html#method-inlineAll) method tries to initialize inline editor also on elements with an editor already attached to them.
+* [#3961](https://github.com/ckeditor/ckeditor4/issues/3961): Fixed: The [Table Resize](https://ckeditor.com/cke4/addon/tableresize) plugin prevents editing of merged cells.
+* [#3649](https://github.com/ckeditor/ckeditor4/issues/3649): Fixed: Applying a [block format](https://ckeditor.com/docs/ckeditor4/latest/features/format.html) should remove existing block styles.
+* [#4282](https://github.com/ckeditor/ckeditor4/issues/4282): Fixed: The [script loader](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_scriptLoader.html) does not execute callback for scripts already loaded when called for the second time. Thanks to [Alexander Korotkevich](https://github.com/aldoom)!
+* [#4273](https://github.com/ckeditor/ckeditor4/issues/4273): Fixed: A memory leak in the [`CKEDITOR.domReady()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR.html#method-domReady) method connected with not removing `load` event listeners. Thanks to [rohit1](https://github.com/rohit1)!
+* [#1330](https://github.com/ckeditor/ckeditor4/issues/1330): Fixed: Incomplete CSS margin parsing if an `auto` or `0` value is used.
+* [#4286](https://github.com/ckeditor/ckeditor4/issues/4286): Fixed: The [Auto Grow](https://ckeditor.com/cke4/addon/autogrow) plugin causes the editor width to be set to `0` on editor resize.
+* [#848](https://github.com/ckeditor/ckeditor4/issues/848): Fixed: Arabic text not being "bound" correctly when pasting. Thanks to [Thomas Hunkapiller](https://github.com/devoidfury) and [J. Ivan Duarte Rodríguez](https://github.com/jidrone-mbm)!
+
+API Changes:
+
+* [#3649](https://github.com/ckeditor/ckeditor4/issues/3649): Added a new [`stylesRemove`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#event-stylesRemove) editor event.
+
+Other Changes:
+
+* [#4262](https://github.com/ckeditor/ckeditor4/issues/4262): Removed the global reference to the `stylesLoaded` variable. Thanks to [Levi Carter](https://github.com/swiftMessenger)!
+* Updated the [Export to PDF](https://ckeditor.com/cke4/addon/exportpdf) plugin to `1.0.1` version:
+ * Improved external CSS support for [classic editor](https://ckeditor.com/docs/ckeditor4/latest/examples/classic.html) by handling exceptions and displaying convenient [error messages](https://ckeditor.com/docs/ckeditor4/latest/guide/dev_errors.html#exportpdf-stylesheets-incaccessible).
+
+## CKEditor 4.15
+
+New features:
+
+* [#3940](https://github.com/ckeditor/ckeditor4/issues/3940): Introduced the `colorName` property for customizing foreground and background styles in the [Color Button](https://ckeditor.com/cke4/addon/colorbutton) plugin via the [`config.colorButton_foreStyle`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-colorButton_foreStyle) and [`config.colorButton_backStyle`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-colorButton_backStyle) configuration options.
+* [#3793](https://github.com/ckeditor/ckeditor4/issues/3793): Introduced the [Editor Placeholder](https://ckeditor.com/cke4/addon/editorplaceholder) plugin.
+* [#1795](https://github.com/ckeditor/ckeditor4/issues/1795): The colors picked from the [Color Dialog](https://ckeditor.com/cke4/addon/colordialog) are now stored in the [Color Button](https://ckeditor.com/cke4/addon/colorbutton) palette and can be reused easily.
+* [#3783](https://github.com/ckeditor/ckeditor4/issues/3783): The colors used in the document are now displayed as a part of the [Color Button](https://ckeditor.com/cke4/addon/colorbutton) palette.
+
+Fixed Issues:
+
+* [#4060](https://github.com/ckeditor/ckeditor4/issues/4060): Fixed: The content inside a [widget](https://ckeditor.com/cke4/addon/widget) nested editable is escaped twice.
+* [#4183](https://github.com/ckeditor/ckeditor4/issues/4183): [Safari] Fixed: Incorrect image dimensions when using the [Easy Image](https://ckeditor.com/cke4/addon/easyimage) plugin alongside the [IFrame Editing Area](https://ckeditor.com/cke4/addon/wysiwygarea) plugin.
+* [#3693](https://github.com/ckeditor/ckeditor4/issues/3693): Fixed: Incorrect default values for several [Color Button](https://ckeditor.com/cke4/addon/colorbutton) configuration variables in the API documentation.
+* [#3795](https://github.com/ckeditor/ckeditor4/issues/3795): Fixed: Setting the [`config.dataIndentationChars`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-dataIndentationChars) configuration option to an empty string is ignored and replaced by a tab (`\t`) character. Thanks to [Thomas Grinderslev](https://github.com/Znegl)!
+* [#4107](https://github.com/ckeditor/ckeditor4/issues/4107): Fixed: Multiple [Autocomplete](https://ckeditor.com/cke4/addon/autocomplete) instances cause keyboard navigation issues.
+* [#4041](https://github.com/ckeditor/ckeditor4/issues/4041): Fixed: The[`selection.scrollIntoView`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_dom_selection.html#method-scrollIntoView) method throws an error when the editor selection is not set.
+* [#3361](https://github.com/ckeditor/ckeditor4/issues/3361): Fixed: Loading multiple [custom editor configurations](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html#cfg-customConfig) is prone to a race condition between these.
+* [#4007](https://github.com/ckeditor/ckeditor4/issues/4007): Fixed: Screen readers do not announce the [Rich Combo](https://ckeditor.com/cke4/addon/richcombo) plugin is collapsed or expanded.
+* [#4141](https://github.com/ckeditor/ckeditor4/issues/4141): Fixed: The styles are incorrectly applied when there is a `
';
+ print ' ';
+}
+
+
print ' ';
dol_htmloutput_errors($errmsg);
-if (!empty($conference->id) && $conference->status==ConferenceOrBooth::STATUS_CONFIRMED || (!empty($project->id) && $project->status==Project::STATUS_VALIDATED)) {
- // Print form
- print '\n";
- print " ";
- print '';
} else {
print $langs->trans("ConferenceIsNotConfirmed");
}
diff --git a/htdocs/public/members/new.php b/htdocs/public/members/new.php
index 055ffec56f9..7a27ae14b62 100644
--- a/htdocs/public/members/new.php
+++ b/htdocs/public/members/new.php
@@ -57,7 +57,6 @@ if (!defined('NOIPCHECK')) {
// For MultiCompany module.
// Do not use GETPOST here, function is not defined and define must be done before including main.inc.php
-// TODO This should be useless. Because entity must be retrieve from object ref and not from url.
$entity = (!empty($_GET['entity']) ? (int) $_GET['entity'] : (!empty($_POST['entity']) ? (int) $_POST['entity'] : 1));
if (is_numeric($entity)) {
define("DOLENTITY", $entity);
@@ -430,7 +429,7 @@ if (empty($reshook) && $action == 'added') {
llxHeaderVierge($langs->trans("NewMemberForm"));
// Si on a pas ete redirige
- print ' ';
+ print '
';
print '
';
print $langs->trans("NewMemberbyWeb");
print '
';
@@ -448,7 +447,7 @@ if (empty($reshook) && $action == 'added') {
$form = new Form($db);
$formcompany = new FormCompany($db);
$adht = new AdherentType($db);
-$extrafields->fetch_name_optionals_label('adherent'); // fetch optionals attributes and labels
+$extrafields->fetch_name_optionals_label($object->table_element); // fetch optionals attributes and labels
llxHeaderVierge($langs->trans("NewSubscription"));
diff --git a/htdocs/public/partnership/new.php b/htdocs/public/partnership/new.php
index cbc1b849115..f6f0efc4fb2 100644
--- a/htdocs/public/partnership/new.php
+++ b/htdocs/public/partnership/new.php
@@ -419,7 +419,7 @@ if (empty($reshook) && $action == 'added') {
llxHeaderVierge($langs->trans("NewPartnershipForm"));
// Si on a pas ete redirige
- print ' ';
+ print '
';
@@ -437,7 +437,7 @@ if (empty($reshook) && $action == 'added') {
$form = new Form($db);
$formcompany = new FormCompany($db);
-$extrafields->fetch_name_optionals_label('partnership'); // fetch optionals attributes and labels
+$extrafields->fetch_name_optionals_label($partnership->table_element); // fetch optionals attributes and labels
llxHeaderVierge($langs->trans("NewPartnershipRequest"));
diff --git a/htdocs/public/project/new.php b/htdocs/public/project/new.php
index 971031e7a80..4838c88c5a1 100644
--- a/htdocs/public/project/new.php
+++ b/htdocs/public/project/new.php
@@ -45,7 +45,6 @@ if (!defined('NOIPCHECK')) {
// For MultiCompany module.
// Do not use GETPOST here, function is not defined and define must be done before including main.inc.php
-// TODO This should be useless. Because entity must be retrieve from object ref and not from url.
$entity = (!empty($_GET['entity']) ? (int) $_GET['entity'] : (!empty($_POST['entity']) ? (int) $_POST['entity'] : 1));
if (is_numeric($entity)) {
define("DOLENTITY", $entity);
@@ -132,9 +131,9 @@ function llxHeaderVierge($title, $head = "", $disablejs = 0, $disablehead = 0, $
print '';
}
- if (!empty($conf->global->PROJECT_IMAGE_PUBLIC_ORGANIZEDEVENT)) {
- print '
'."\n";
+
// Other attributes
$tpl_context = 'public'; // define template context to public
include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_add.tpl.php';
// Comments
print '
';
-print '
'.$langs->trans("Comments").'
';
-print '
';
+print '
'.$langs->trans("Message").' *
';
+print '
';
print '
'."\n";
print "
\n";
diff --git a/htdocs/public/ticket/ajax/ajax.php b/htdocs/public/ticket/ajax/ajax.php
new file mode 100644
index 00000000000..a75c796539c
--- /dev/null
+++ b/htdocs/public/ticket/ajax/ajax.php
@@ -0,0 +1,87 @@
+
+ *
+ * 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 .
+ */
+
+/**
+ * \file htdocs/public/ticket/ajax/ajax.php
+ * \brief Ajax component for Ticket.
+ */
+
+if (!defined('NOTOKENRENEWAL')) {
+ define('NOTOKENRENEWAL', '1'); // Disables token renewal
+}
+if (!defined('NOREQUIREHTML')) {
+ define('NOREQUIREHTML', '1');
+}
+if (!defined('NOREQUIREAJAX')) {
+ define('NOREQUIREAJAX', '1');
+}
+if (!defined('NOREQUIRESOC')) {
+ define('NOREQUIRESOC', '1');
+}
+if (!defined('NOCSRFCHECK')) {
+ define('NOCSRFCHECK', '1');
+}
+// Do not check anti CSRF attack test
+if (!defined('NOREQUIREMENU')) {
+ define('NOREQUIREMENU', '1');
+}
+// If there is no need to load and show top and left menu
+if (!defined("NOLOGIN")) {
+ define("NOLOGIN", '1');
+}
+if (!defined('NOIPCHECK')) {
+ define('NOIPCHECK', '1'); // Do not check IP defined into conf $dolibarr_main_restrict_ip
+}
+if (!defined('NOBROWSERNOTIF')) {
+ define('NOBROWSERNOTIF', '1');
+}
+
+include_once '../../../main.inc.php'; // Load $user and permissions
+
+$action = GETPOST('action', 'aZ09');
+$id = GETPOST('id', 'int');
+$email = GETPOST('email', 'alphanohtml');
+
+
+/*
+ * View
+ */
+
+top_httphead();
+
+if ($action == 'getContacts') {
+ $return = array(
+ 'contacts' => array(),
+ 'error' => '',
+ );
+
+ if (!empty($email)) {
+ require_once DOL_DOCUMENT_ROOT.'/ticket/class/ticket.class.php';
+
+ $ticket = new Ticket($db);
+ $contacts = $ticket->searchContactByEmail($email);
+ if (is_array($contacts)) {
+ $return['contacts'] = $contacts;
+ } else {
+ $return['error'] = $ticket->errorsToString();
+ }
+ }
+
+ echo json_encode($return);
+ exit();
+}
diff --git a/htdocs/public/ticket/create_ticket.php b/htdocs/public/ticket/create_ticket.php
index 371789edc62..f7e6e023a7f 100644
--- a/htdocs/public/ticket/create_ticket.php
+++ b/htdocs/public/ticket/create_ticket.php
@@ -63,6 +63,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/payments.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php';
+require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
// Load translation files required by the page
$langs->loadLangs(array('companies', 'other', 'mails', 'ticket'));
@@ -78,6 +79,11 @@ $hookmanager->initHooks(array('publicnewticketcard', 'globalcard'));
$object = new Ticket($db);
$extrafields = new ExtraFields($db);
+$contacts = array();
+$with_contact = null;
+if (!empty($conf->global->TICKET_CREATE_THIRD_PARTY_WITH_CONTACT_IF_NOT_EXIST)) {
+ $with_contact = new Contact($db);
+}
$extrafields->fetch_name_optionals_label($object->table_element);
@@ -153,18 +159,50 @@ if (empty($reshook) && $action == 'create_ticket' && GETPOST('save', 'alpha')) {
}
}
+ $contact_lastname = '';
+ $contact_firstname = '';
+ $company_name = '';
+ $contact_phone = '';
+ if ($with_contact) {
+ // set linked contact to add in form
+ if (is_array($contacts) && count($contacts) == 1) {
+ $with_contact = current($contacts);
+ }
+
+ // check mandatory fields on contact
+ $contact_lastname = trim(GETPOST('contact_lastname', 'alphanohtml'));
+ $contact_firstname = trim(GETPOST('contact_firstname', 'alphanohtml'));
+ $company_name = trim(GETPOST('company_name', 'alphanohtml'));
+ $contact_phone = trim(GETPOST('contact_phone', 'alphanohtml'));
+ if (!($with_contact->id > 0)) {
+ // check lastname
+ if (empty($contact_lastname)) {
+ $error++;
+ array_push($object->errors, $langs->trans('ErrorFieldRequired', $langs->transnoentities('Lastname')));
+ $action = '';
+ }
+ // check firstname
+ if (empty($contact_firstname)) {
+ $error++;
+ array_push($object->errors, $langs->trans('ErrorFieldRequired', $langs->transnoentities('Firstname')));
+ $action = '';
+ }
+ }
+ }
+
if (!GETPOST("subject", "restricthtml")) {
$error++;
array_push($object->errors, $langs->trans("ErrorFieldRequired", $langs->transnoentities("Subject")));
$action = '';
- } elseif (!GETPOST("message", "restricthtml")) {
+ }
+ if (!GETPOST("message", "restricthtml")) {
$error++;
- array_push($object->errors, $langs->trans("ErrorFieldRequired", $langs->transnoentities("message")));
+ array_push($object->errors, $langs->trans("ErrorFieldRequired", $langs->transnoentities("Message")));
$action = '';
}
// Check email address
- if (!isValidEmail($origin_email)) {
+ if (!empty($origin_email) && !isValidEmail($origin_email)) {
$error++;
array_push($object->errors, $langs->trans("ErrorBadEmailAddress", $langs->transnoentities("email")));
$action = '';
@@ -193,6 +231,48 @@ if (empty($reshook) && $action == 'create_ticket' && GETPOST('save', 'alpha')) {
$object->type_code = GETPOST("type_code", 'aZ09');
$object->category_code = GETPOST("category_code", 'aZ09');
$object->severity_code = GETPOST("severity_code", 'aZ09');
+
+ if (!is_object($user)) {
+ $user = new User($db);
+ }
+
+ // create third-party with contact
+ $usertoassign = 0;
+ if ($with_contact && !($with_contact->id > 0)) {
+ $company = new Societe($db);
+ if (!empty($company_name)) {
+ $company->name = $company_name;
+ } else {
+ $company->particulier = 1;
+ $company->name = dolGetFirstLastname($contact_firstname, $contact_lastname);
+ }
+ $result = $company->create($user);
+ if ($result < 0) {
+ $error++;
+ $errors = ($company->error ? array($company->error) : $company->errors);
+ array_push($object->errors, $errors);
+ $action = 'create_ticket';
+ }
+
+ // create contact and link to this new company
+ if (!$error) {
+ $with_contact->email = $origin_email;
+ $with_contact->lastname = $contact_lastname;
+ $with_contact->firstname = $contact_firstname;
+ $with_contact->socid = $company->id;
+ $with_contact->phone_pro = $contact_phone;
+ $result = $with_contact->create($user);
+ if ($result < 0) {
+ $error++;
+ $errors = ($with_contact->error ? array($with_contact->error) : $with_contact->errors);
+ array_push($object->errors, $errors);
+ $action = 'create_ticket';
+ } else {
+ $contacts = array($with_contact);
+ }
+ }
+ }
+
if (is_array($searched_companies)) {
$object->fk_soc = $searched_companies[0]->id;
}
@@ -206,9 +286,6 @@ if (empty($reshook) && $action == 'create_ticket' && GETPOST('save', 'alpha')) {
// Generate new ref
$object->ref = $object->getDefaultRef();
- if (!is_object($user)) {
- $user = new User($db);
- }
$object->context['disableticketemail'] = 1; // Disable emails sent by ticket trigger when creation is done from this page, emails are already sent later
@@ -402,7 +479,7 @@ if ($action != "infos_success") {
print '
';
} else {
print '
'.$langs->trans('TicketPublicInfoCreateTicket').'
';
- $formticket->showForm(0, 'edit', 1);
+ $formticket->showForm(0, 'edit', 1, $with_contact);
}
}
diff --git a/htdocs/reception/card.php b/htdocs/reception/card.php
index 0586f004e20..cdd82525b6e 100644
--- a/htdocs/reception/card.php
+++ b/htdocs/reception/card.php
@@ -350,8 +350,10 @@ if (empty($reshook)) {
}
$qty = "qtyl".$i;
$comment = "comment".$i;
- $eatby = "dlc".$i;
- $sellby = "dluo".$i;
+ // EATBY <-> DLUO see productbatch.class.php
+ // SELLBY <-> DLC
+ $eatby = "dluo".$i;
+ $sellby = "dlc".$i;
$batch = "batch".$i;
$cost_price = "cost_price".$i;
@@ -626,9 +628,11 @@ if (empty($reshook)) {
$batch = "batch".$line_id;
$dlc = "dlc".$line_id;
$dluo = "dluo".$line_id;
- $eatby = GETPOST($dlc, 'alpha');
+ // EATBY <-> DLUO
+ $eatby = GETPOST($dluo, 'alpha');
$eatbydate = str_replace('/', '-', $eatby);
- $sellby = GETPOST($dluo, 'alpha');
+ // SELLBY <-> DLC
+ $sellby = GETPOST($dlc, 'alpha');
$sellbydate = str_replace('/', '-', $sellby);
$line->batch = GETPOST($batch, 'alpha');
$line->eatby = strtotime($eatbydate);
@@ -639,8 +643,7 @@ if (empty($reshook)) {
setEventMessages($line->error, $line->errors, 'errors');
$error++;
}
- } else // Product no predefined
- {
+ } else { // Product no predefined
$qty = "qtyl".$line_id;
$line->id = $line_id;
$line->qty = GETPOST($qty, 'int');
diff --git a/htdocs/recruitment/class/recruitmentcandidature.class.php b/htdocs/recruitment/class/recruitmentcandidature.class.php
index 77b5b5b21ae..fb08409eb27 100644
--- a/htdocs/recruitment/class/recruitmentcandidature.class.php
+++ b/htdocs/recruitment/class/recruitmentcandidature.class.php
@@ -62,6 +62,11 @@ class RecruitmentCandidature extends CommonObject
*/
public $picto = 'recruitmentcandidature';
+ /**
+ * @var int Do not exploit fields email_xxx into triggers.
+ */
+ public $email_fields_no_propagate_in_actioncomm;
+
const STATUS_DRAFT = 0;
const STATUS_VALIDATED = 1;
diff --git a/htdocs/recruitment/recruitmentcandidature_card.php b/htdocs/recruitment/recruitmentcandidature_card.php
index eca3a497e61..186864deb84 100644
--- a/htdocs/recruitment/recruitmentcandidature_card.php
+++ b/htdocs/recruitment/recruitmentcandidature_card.php
@@ -134,7 +134,9 @@ if (empty($reshook)) {
$triggermodname = 'RECRUITMENTCANDIDATURE_MODIFY'; // Name of trigger action code to execute when we modify record
// Actions cancel, add, update, update_extras, confirm_validate, confirm_delete, confirm_deleteline, confirm_clone, confirm_close, confirm_setdraft, confirm_reopen
+ $object->email_fields_no_propagate_in_actioncomm = 1;
include DOL_DOCUMENT_ROOT.'/core/actions_addupdatedelete.inc.php';
+ $object->email_fields_no_propagate_in_actioncomm = 0;
// Actions when linking object each other
include DOL_DOCUMENT_ROOT.'/core/actions_dellink.inc.php';
diff --git a/htdocs/societe/ajax/company.php b/htdocs/societe/ajax/company.php
index 9dfe3909393..5c02afe85dc 100644
--- a/htdocs/societe/ajax/company.php
+++ b/htdocs/societe/ajax/company.php
@@ -109,7 +109,6 @@ if (!empty($action) && $action == 'fetch' && !empty($id)) {
// When used from jQuery, the search term is added as GET param "term".
$searchkey = (($id && GETPOST($id, 'alpha')) ? GETPOST($id, 'alpha') : (($htmlname && GETPOST($htmlname, 'alpha')) ?GETPOST($htmlname, 'alpha') : ''));
-
if (!$searchkey) {
return;
}
diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php
index 1d32063c27b..30f8515e92c 100644
--- a/htdocs/societe/class/societe.class.php
+++ b/htdocs/societe/class/societe.class.php
@@ -956,7 +956,7 @@ class Societe extends CommonObject
$sql .= ", accountancy_code_sell";
$sql .= ") VALUES (";
$sql .= $this->id;
- $sql .= ", ".$conf->entity;
+ $sql .= ", ".((int) $conf->entity);
$sql .= ", '".$this->db->escape($this->accountancy_code_customer)."'";
$sql .= ", '".$this->db->escape($this->accountancy_code_supplier)."'";
$sql .= ", '".$this->db->escape($this->accountancy_code_buy)."'";
diff --git a/htdocs/societe/index.php b/htdocs/societe/index.php
index eb0c1e35230..8cae5ef49f8 100644
--- a/htdocs/societe/index.php
+++ b/htdocs/societe/index.php
@@ -353,8 +353,8 @@ if ($result) {
$lastmodified .= $thirdparty_static->getTypeUrl();
$lastmodified .= '';
// Last modified date
- $lastmodified .= '
';
diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php
index 33ca6d0ec9c..9f25d49bd50 100644
--- a/htdocs/user/class/user.class.php
+++ b/htdocs/user/class/user.class.php
@@ -80,6 +80,7 @@ class User extends CommonObject
* @var string gender
*/
public $gender;
+
public $birth;
/**
@@ -717,7 +718,8 @@ class User extends CommonObject
'knowledgerecord' => 'knowledgerecord@knowledgemanagement',
'skill@hrm' => 'all@hrm', // skill / job / position objects rights are for the moment grouped into right level "all"
'job@hrm' => 'all@hrm', // skill / job / position objects rights are for the moment grouped into right level "all"
- 'position@hrm' => 'all@hrm' // skill / job / position objects rights are for the moment grouped into right level "all"
+ 'position@hrm' => 'all@hrm', // skill / job / position objects rights are for the moment grouped into right level "all"
+ 'facturerec' => 'facture'
);
if (!empty($moduletomoduletouse[$module])) {
$module = $moduletomoduletouse[$module];
diff --git a/htdocs/user/list.php b/htdocs/user/list.php
index 422d36d791f..2ec8ac37b87 100644
--- a/htdocs/user/list.php
+++ b/htdocs/user/list.php
@@ -661,7 +661,7 @@ if (!empty($arrayfields['u.firstname']['checked'])) {
print '
';
}
if (!empty($arrayfields['u.gender']['checked'])) {
- print '