Browse Source

Merge branch '18.0' of git@github.com:Dolibarr/dolibarr.git into develop

Laurent Destailleur 1 year ago
parent
commit
fc94e39d58

+ 111 - 81
htdocs/admin/menus/edit.php

@@ -71,65 +71,6 @@ if (GETPOST("menu_handler")) {
  * Actions
  */
 
-if ($action == 'update') {
-	if (!$cancel) {
-		$leftmenu = ''; $mainmenu = '';
-		if (GETPOST('menuIdParent', 'alphanohtml') && !is_numeric(GETPOST('menuIdParent', 'alphanohtml'))) {
-			$tmp = explode('&', GETPOST('menuIdParent', 'alphanohtml'));
-			foreach ($tmp as $s) {
-				if (preg_match('/fk_mainmenu=/', $s)) {
-					$mainmenu = preg_replace('/fk_mainmenu=/', '', $s);
-				}
-				if (preg_match('/fk_leftmenu=/', $s)) {
-					$leftmenu = preg_replace('/fk_leftmenu=/', '', $s);
-				}
-			}
-		}
-
-		$menu = new Menubase($db);
-		$result = $menu->fetch(GETPOST('menuId', 'int'));
-		if ($result > 0) {
-			$menu->title = (string) GETPOST('titre', 'alphanohtml');
-			$menu->leftmenu = (string) GETPOST('leftmenu', 'aZ09');
-			$menu->url = (string) GETPOST('url', 'alphanohtml');
-			$menu->langs = (string) GETPOST('langs', 'alphanohtml');
-			$menu->position = (int) GETPOST('position', 'int');
-			$menu->enabled = (string) GETPOST('enabled', 'alphanohtml');
-			$menu->perms = (string) GETPOST('perms', 'alphanohtml');
-			$menu->target = (string) GETPOST('target', 'alphanohtml');
-			$menu->user = (string) GETPOST('user', 'alphanohtml');
-			$menu->mainmenu = (string) GETPOST('propertymainmenu', 'alphanohtml');
-			if (is_numeric(GETPOST('menuIdParent', 'alphanohtml'))) {
-				$menu->fk_menu = (int) GETPOST('menuIdParent', 'alphanohtml');
-			} else {
-				if (GETPOST('type', 'alphanohtml') == 'top') {
-					$menu->fk_menu = 0;
-				} else {
-					$menu->fk_menu = -1;
-				}
-				$menu->fk_mainmenu = $mainmenu;
-				$menu->fk_leftmenu = $leftmenu;
-			}
-
-			$result = $menu->update($user);
-			if ($result > 0) {
-				setEventMessages($langs->trans("RecordModifiedSuccessfully"), null, 'mesgs');
-			} else {
-				setEventMessages($menu->error, $menu->errors, 'errors');
-			}
-		} else {
-			setEventMessages($menu->error, $menu->errors, 'errors');
-		}
-		$action = "edit";
-
-		header("Location: ".DOL_URL_ROOT."/admin/menus/index.php?menu_handler=".$menu_handler);
-		exit;
-	} else {
-		header("Location: ".DOL_URL_ROOT."/admin/menus/index.php?menu_handler=".$menu_handler);
-		exit;
-	}
-}
-
 if ($action == 'add') {
 	if ($cancel) {
 		header("Location: ".DOL_URL_ROOT."/admin/menus/index.php?menu_handler=".$menu_handler);
@@ -138,8 +79,8 @@ if ($action == 'add') {
 
 	$leftmenu = '';
 	$mainmenu = '';
-	if (GETPOST('menuId', 'alphanohtml', 3) && !is_numeric(GETPOST('menuId', 'alphanohtml', 3))) {
-		$tmp = explode('&', GETPOST('menuId', 'alphanohtml', 3));
+	if (GETPOST('menuIdParent', 'alphanohtml') && !is_numeric(GETPOST('menuIdParent', 'alphanohtml'))) {
+		$tmp = explode('&', GETPOST('menuIdParent', 'alphanohtml'));
 		foreach ($tmp as $s) {
 			if (preg_match('/fk_mainmenu=/', $s)) {
 				$mainmenu = preg_replace('/fk_mainmenu=/', '', $s);
@@ -173,12 +114,12 @@ if ($action == 'add') {
 		$action = 'create';
 		$error++;
 	}
-	if (!$error && GETPOST('menuId', 'alphanohtml', 3) && GETPOST('type') == 'top') {
+	if (!$error && GETPOST('menuIdParent', 'alphanohtml') && GETPOST('type') == 'top') {
 		setEventMessages($langs->trans("ErrorTopMenuMustHaveAParentWithId0"), null, 'errors');
 		$action = 'create';
 		$error++;
 	}
-	if (!$error && !GETPOST('menuId', 'alphanohtml', 3) && GETPOST('type') == 'left') {
+	if (!$error && !GETPOST('menuIdParent', 'alphanohtml') && GETPOST('type') == 'left') {
 		setEventMessages($langs->trans("ErrorLeftMenuMustHaveAParentId"), null, 'errors');
 		$action = 'create';
 		$error++;
@@ -189,6 +130,7 @@ if ($action == 'add') {
 		$menu->menu_handler = preg_replace('/_menu$/', '', GETPOST('menu_handler', 'aZ09'));
 		$menu->type = (string) GETPOST('type', 'alphanohtml');
 		$menu->title = (string) GETPOST('titre', 'alphanohtml');
+		$menu->prefix = (string) GETPOST('picto', 'restricthtmlallowclass');
 		$menu->url = (string) GETPOST('url', 'alphanohtml');
 		$menu->langs = (string) GETPOST('langs', 'alphanohtml');
 		$menu->position = (int) GETPOST('position', 'int');
@@ -197,8 +139,8 @@ if ($action == 'add') {
 		$menu->target = (string) GETPOST('target', 'alphanohtml');
 		$menu->user = (string) GETPOST('user', 'alphanohtml');
 		$menu->mainmenu = (string) GETPOST('propertymainmenu', 'alphanohtml');
-		if (is_numeric(GETPOST('menuId', 'alphanohtml', 3))) {
-			$menu->fk_menu = (int) GETPOST('menuId', 'alphanohtml', 3);
+		if (is_numeric(GETPOST('menuIdParent', 'alphanohtml'))) {
+			$menu->fk_menu = (int) GETPOST('menuIdParent', 'alphanohtml');
 		} else {
 			if (GETPOST('type', 'alphanohtml') == 'top') {
 				$menu->fk_menu = 0;
@@ -220,6 +162,78 @@ if ($action == 'add') {
 	}
 }
 
+if ($action == 'update') {
+	if (!$cancel) {
+		$leftmenu = ''; $mainmenu = '';
+		if (GETPOST('menuIdParent', 'alphanohtml') && !is_numeric(GETPOST('menuIdParent', 'alphanohtml'))) {
+			$tmp = explode('&', GETPOST('menuIdParent', 'alphanohtml'));
+			foreach ($tmp as $s) {
+				if (preg_match('/fk_mainmenu=/', $s)) {
+					$mainmenu = preg_replace('/fk_mainmenu=/', '', $s);
+				}
+				if (preg_match('/fk_leftmenu=/', $s)) {
+					$leftmenu = preg_replace('/fk_leftmenu=/', '', $s);
+				}
+			}
+		}
+
+		$error = 0;
+		if (!$error && !GETPOST('url')) {
+			setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("URL")), null, 'errors');
+			$action = 'create';
+			$error++;
+		}
+
+		if (!$error) {
+			$menu = new Menubase($db);
+			$result = $menu->fetch(GETPOST('menuId', 'int'));
+			if ($result > 0) {
+				$menu->title = (string) GETPOST('titre', 'alphanohtml');
+				$menu->prefix = (string) GETPOST('picto', 'restricthtmlallowclass');
+				$menu->leftmenu = (string) GETPOST('leftmenu', 'aZ09');
+				$menu->url = (string) GETPOST('url', 'alphanohtml');
+				$menu->langs = (string) GETPOST('langs', 'alphanohtml');
+				$menu->position = (int) GETPOST('position', 'int');
+				$menu->enabled = (string) GETPOST('enabled', 'alphanohtml');
+				$menu->perms = (string) GETPOST('perms', 'alphanohtml');
+				$menu->target = (string) GETPOST('target', 'alphanohtml');
+				$menu->user = (string) GETPOST('user', 'alphanohtml');
+				$menu->mainmenu = (string) GETPOST('propertymainmenu', 'alphanohtml');
+				if (is_numeric(GETPOST('menuIdParent', 'alphanohtml'))) {
+					$menu->fk_menu = (int) GETPOST('menuIdParent', 'alphanohtml');
+				} else {
+					if (GETPOST('type', 'alphanohtml') == 'top') {
+						$menu->fk_menu = 0;
+					} else {
+						$menu->fk_menu = -1;
+					}
+					$menu->fk_mainmenu = $mainmenu;
+					$menu->fk_leftmenu = $leftmenu;
+				}
+
+				$result = $menu->update($user);
+				if ($result > 0) {
+					setEventMessages($langs->trans("RecordModifiedSuccessfully"), null, 'mesgs');
+				} else {
+					setEventMessages($menu->error, $menu->errors, 'errors');
+				}
+			} else {
+				setEventMessages($menu->error, $menu->errors, 'errors');
+			}
+
+			$action = "edit";
+
+			header("Location: ".DOL_URL_ROOT."/admin/menus/index.php?menu_handler=".$menu_handler);
+			exit;
+		} else {
+			$action = 'edit';
+		}
+	} else {
+		header("Location: ".DOL_URL_ROOT."/admin/menus/index.php?menu_handler=".$menu_handler);
+		exit;
+	}
+}
+
 
 
 /*
@@ -239,14 +253,14 @@ if ($action == 'create') {
     	{
     		if (jQuery("#topleft").val() == \'top\')
     		{
-				jQuery("#menuId").prop("disabled", true);
-	    		jQuery("#menuId").val(\'\');
+				jQuery("#menuIdParent").prop("disabled", true);
+	    		jQuery("#menuIdParent").val(\'\');
 				jQuery("#propertymainmenu").removeAttr("disabled");
 	    		jQuery("#propertymainmenu").val(\'\');
 			}
     		if (jQuery("#topleft").val() == \'left\')
     		{
-				jQuery("#menuId").removeAttr("disabled");
+				jQuery("#menuIdParent").removeAttr("disabled");
 				jQuery("#propertymainmenu").prop("disabled", true);
     		}
     	}
@@ -264,6 +278,7 @@ if ($action == 'create') {
 
 	print dol_get_fiche_head();
 
+	print '<div class="div-table-responsive">'; // You can use div-table-responsive-no-min if you dont need reserved height for your table
 	print '<table class="border centpercent">';
 
 	// Id
@@ -274,7 +289,9 @@ if ($action == 'create') {
 	$parent_level = '';
 
 	if (GETPOST('menuId', 'int')) {
-		$sql = "SELECT m.rowid, m.mainmenu, m.leftmenu, m.level, m.langs FROM ".MAIN_DB_PREFIX."menu as m WHERE m.rowid = ".GETPOST('menuId', 'int');
+		$sql = "SELECT m.rowid, m.mainmenu, m.leftmenu, m.level, m.langs";
+		$sql .= " FROM ".MAIN_DB_PREFIX."menu as m";
+		$sql .= " WHERE m.rowid = ".((int) GETPOST('menuId', 'int'));
 		$res = $db->query($sql);
 		if ($res) {
 			while ($menu = $db->fetch_array($res)) {
@@ -330,9 +347,9 @@ if ($action == 'create') {
 	// MenuId Parent
 	print '<tr><td class="fieldrequired">'.$langs->trans('MenuIdParent').'</td>';
 	if ($parent_rowid) {
-		print '<td>'.$parent_rowid.'<input type="hidden" name="menuId" value="'.$parent_rowid.'"></td>';
+		print '<td>'.$parent_rowid.'<input type="hidden" name="menuIdParent" value="'.$parent_rowid.'"></td>';
 	} else {
-		print '<td><input type="text" class="minwidth300" id="menuId" name="menuId" value="'.(GETPOSTISSET("menuId") ? GETPOST("menuId", 'int') : '').'"></td>';
+		print '<td><input type="text" class="minwidth300" id="menuIdParent" name="menuIdParent" value="'.(GETPOSTISSET("menuIdParent") ? GETPOST("menuIdParent", 'alphanohtml') : '').'"></td>';
 	}
 	print '<td>'.$langs->trans('DetailMenuIdParent');
 	print ', '.$langs->trans("Example").': fk_mainmenu=abc&fk_leftmenu=def';
@@ -342,17 +359,21 @@ if ($action == 'create') {
 	print '<tr><td class="fieldrequired">'.$langs->trans('Title').'</td>';
 	print '<td><input type="text" class="minwidth300" name="titre" value="'.dol_escape_htmltag(GETPOST("titre", 'alphanohtml')).'"></td><td>'.$langs->trans('DetailTitre').'</td></tr>';
 
+	// Picto
+	print '<tr><td class="fieldrequired">'.$langs->trans('Image').'</td>';
+	print '<td><input type="text" class="minwidth300" name="picto" value="'.dol_escape_htmltag(GETPOST("picto", 'alphanohtmlallowclass')).'"></td><td>'.$langs->trans('Example').': fa-global</td></tr>';
+
 	// URL
 	print '<tr><td class="fieldrequired">'.$langs->trans('URL').'</td>';
-	print '<td><input type="text" class="minwidth500" name="url" value="'.GETPOST("url", 'alphanohtml').'"></td><td>'.$langs->trans('DetailUrl').'</td></tr>';
+	print '<td><input type="text" class="minwidth500" name="url" value="'.dol_escape_htmltag(GETPOST("url", 'alphanohtml')).'"></td><td>'.$langs->trans('DetailUrl').'</td></tr>';
 
 	// Langs
 	print '<tr><td>'.$langs->trans('LangFile').'</td>';
-	print '<td><input type="text" class="minwidth300" name="langs" value="'.$parent_langs.'"></td><td>'.$langs->trans('DetailLangs').'</td></tr>';
+	print '<td><input type="text" class="minwidth300" name="langs" value="'.dol_escape_htmltag($parent_langs).'"></td><td>'.$langs->trans('DetailLangs').'</td></tr>';
 
 	// Position
 	print '<tr><td>'.$langs->trans('Position').'</td>';
-	print '<td><input type="text" class="width100" name="position" value="'.dol_escape_htmltag(GETPOSTISSET("position") ? GETPOST("position", 'int') : 100).'"></td><td>'.$langs->trans('DetailPosition').'</td></tr>';
+	print '<td><input type="text" class="width100" name="position" value="'.((int) (GETPOSTISSET("position") ? GETPOSTINT("position") : 100)).'"></td><td>'.$langs->trans('DetailPosition').'</td></tr>';
 
 	// Enabled
 	print '<tr><td>'.$langs->trans('Enabled').'</td>';
@@ -371,6 +392,7 @@ if ($action == 'create') {
 	print '</td></td><td>'.$langs->trans('DetailTarget').'</td></tr>';
 
 	print '</table>';
+	print '</div>';
 
 	print dol_get_fiche_end();
 
@@ -381,13 +403,15 @@ if ($action == 'create') {
 	print load_fiche_titre($langs->trans("ModifMenu"), '', 'title_setup');
 	print '<br>';
 
-	print '<form action="./edit.php?action=update" method="POST" name="formmenuedit">';
+	print '<form action="./edit.php" method="POST" name="formmenuedit">';
+	print '<input type="hidden" name="action" value="update">';
 	print '<input type="hidden" name="token" value="'.newToken().'">';
 	print '<input type="hidden" name="handler_origine" value="'.$menu_handler.'">';
 	print '<input type="hidden" name="menuId" value="'.GETPOST('menuId', 'int').'">';
 
 	print dol_get_fiche_head();
 
+	print '<div class="div-table-responsive">'; // You can use div-table-responsive-no-min if you dont need reserved height for your table
 	print '<table class="border centpercent">';
 
 	$menu = new Menubase($db);
@@ -431,7 +455,7 @@ if ($action == 'create') {
 		 }
 		 else
 		 {*/
-		print '<td><input type="text" class="minwidth300" id="propertymainmenu" name="propertymainmenu" value="'.(GETPOST("propertymainmenu", 'alphanohtml') ?GETPOST("propertymainmenu", 'alphanohtml') : $menu->mainmenu).'"></td>';
+		print '<td><input type="text" class="minwidth300" id="propertymainmenu" name="propertymainmenu" value="'.(GETPOST("propertymainmenu", 'alphanohtml') ? GETPOST("propertymainmenu", 'alphanohtml') : $menu->mainmenu).'"></td>';
 		//}
 		print '<td>';
 		print $langs->trans("Example").': mytopmenukey';
@@ -448,7 +472,7 @@ if ($action == 'create') {
 	if ($menu->fk_leftmenu) {
 		$valtouse .= '&fk_leftmenu='.$menu->fk_leftmenu;
 	}
-	print '<td><input type="text" name="menuIdParent" value="'.$valtouse.'" class="minwidth300"></td>';
+	print '<td><input type="text" name="menuIdParent" value="'.dol_escape_htmltag(GETPOSTISSET('menuIdParent') ? GETPOST('menuIdParent') : $valtouse).'" class="minwidth300"></td>';
 	print '<td>'.$langs->trans('DetailMenuIdParent');
 	print ', <span class="opacitymedium">'.$langs->trans("Example").': fk_mainmenu=abc&fk_leftmenu=def</span>';
 	print '</td></tr>';
@@ -460,9 +484,13 @@ if ($action == 'create') {
 	print '<tr><td class="fieldrequired">'.$langs->trans('Title').'</td>';
 	print '<td><input type="text" class="minwidth300" name="titre" value="'.dol_escape_htmltag($menu->title).'"></td><td>'.$langs->trans('DetailTitre').'</td></tr>';
 
-	// Url
+	// URL
 	print '<tr><td class="fieldrequired">'.$langs->trans('URL').'</td>';
-	print '<td><input type="text" class="quatrevingtpercent" name="url" value="'.$menu->url.'"></td><td>'.$langs->trans('DetailUrl').'</td></tr>';
+	print '<td><input type="text" class="quatrevingtpercent" name="url" value="'.dol_escape_htmltag($menu->url).'"></td><td>'.$langs->trans('DetailUrl').'</td></tr>';
+
+	// Picto
+	print '<tr><td class="fieldrequired">'.$langs->trans('Image').'</td>';
+	print '<td><input type="text" class="minwidth300" name="picto" value="'.dol_escape_htmltag($menu->prefix).'"></td><td>'.$langs->trans('Example').': fa-global</td></tr>';
 
 	// Langs
 	print '<tr><td>'.$langs->trans('LangFile').'</td>';
@@ -470,7 +498,7 @@ if ($action == 'create') {
 
 	// Position
 	print '<tr><td>'.$langs->trans('Position').'</td>';
-	print '<td><input type="text" class="minwidth100" name="position" value="'.$menu->position.'"></td><td>'.$langs->trans('DetailPosition').'</td></tr>';
+	print '<td><input type="text" class="minwidth100" name="position" value="'.((int) $menu->position).'"></td><td>'.$langs->trans('DetailPosition').'</td></tr>';
 
 	// Enabled
 	print '<tr><td>'.$langs->trans('Enabled').'</td>';
@@ -489,7 +517,8 @@ if ($action == 'create') {
 	print '</td></tr>';
 
 	// Target
-	print '<tr><td>'.$langs->trans('Target').'</td><td><select class="flat" id="target" name="target">';
+	print '<tr><td>'.$langs->trans('Target').'</td><td>';
+	print '<select class="flat" id="target" name="target">';
 	print '<option value=""'.($menu->target == "" ? ' selected' : '').'>&nbsp;</option>';
 	print '<option value="_blank"'.($menu->target == "_blank" ? ' selected' : '').'>'.$langs->trans('_blank').'</option>';
 	print '</select>';
@@ -497,6 +526,7 @@ if ($action == 'create') {
 	print '</td><td>'.$langs->trans('DetailTarget').'</td></tr>';
 
 	print '</table>';
+	print '</div>';
 
 	print dol_get_fiche_end();
 

+ 8 - 0
htdocs/admin/modules.php

@@ -113,6 +113,14 @@ $urldolibarrmodules = 'https://www.dolistore.com/';
 // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
 $hookmanager->initHooks(array('adminmodules', 'globaladmin'));
 
+// Execution Time
+$max_execution_time_for_deploy = (empty($conf->global->MODULE_UPLOAD_MAX_EXECUTION_TIME) ? 300 : $conf->global->MODULE_UPLOAD_MAX_EXECUTION_TIME); // 5mn if not defined
+$max_time = @ini_get("max_execution_time");
+if ($max_time && $max_time < $max_execution_time_for_deploy) {
+	dol_syslog("max_execution_time=".$max_time." is lower than max_execution_time_for_deploy=".$max_execution_time_for_deploy.". We try to increase it dynamically.");
+	@ini_set("max_execution_time", $max_execution_time_for_deploy); // This work only if safe mode is off. also web servers has timeout of 300
+}
+
 
 /*
  * Actions

+ 0 - 2
htdocs/contact/class/contact.class.php

@@ -2194,8 +2194,6 @@ class Contact extends CommonObject
 	 */
 	public function getKanbanView($option = '', $arraydata = null)
 	{
-		global $langs;
-
 		$selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']);
 
 		$return = '<div class="box-flex-item box-flex-grow-zero">';

+ 23 - 11
htdocs/contrat/card.php

@@ -1520,7 +1520,7 @@ if ($action == 'create') {
 
 			// Area with common detail of line
 			print '<div class="div-table-responsive-no-min">';
-			print '<table class="notopnoleftnoright allwidth tableforservicepart1" width="100%">';
+			print '<table class="notopnoleftnoright allwidth tableforservicepart1 centpercent">';
 
 			$sql = "SELECT cd.rowid, cd.statut, cd.label as label_det, cd.fk_product, cd.product_type, cd.description, cd.price_ht, cd.qty,";
 			$sql .= " cd.tva_tx, cd.vat_src_code, cd.remise_percent, cd.info_bits, cd.subprice, cd.multicurrency_subprice,";
@@ -1540,6 +1540,7 @@ if ($action == 'create') {
 
 				$objp = $db->fetch_object($result);
 
+				// Line title
 				print '<tr class="liste_titre'.($cursorline ? ' liste_titre_add' : '').'">';
 				print '<td>'.$langs->trans("ServiceNb", $cursorline).'</td>';
 				print '<td width="80" class="center">'.$langs->trans("VAT").'</td>';
@@ -1584,7 +1585,9 @@ if ($action == 'create') {
 					if (!empty($conf->global->CONTRACT_HIDE_CLOSED_SERVICES_BY_DEFAULT) && $objp->statut == ContratLigne::STATUS_CLOSED && $action != 'showclosedlines') {
 						$moreparam = 'style="display: none;"';
 					}
+
 					print '<tr class="tdtop oddeven" '.$moreparam.'>';
+
 					// Label
 					if ($objp->fk_product > 0) {
 						$productstatic->id = $objp->fk_product;
@@ -1610,7 +1613,7 @@ if ($action == 'create') {
 							$description = ''; // Already added into main visible desc
 						}
 
-						echo $form->textwithtooltip($text, $description, 3, '', '', $cursorline, 0, (!empty($line->fk_parent_line) ?img_picto('', 'rightarrow') : ''));
+						print $form->textwithtooltip($text, $description, 3, '', '', $cursorline, 3, (!empty($line->fk_parent_line) ?img_picto('', 'rightarrow') : ''));
 
 						print '</td>';
 					} else {
@@ -1666,16 +1669,16 @@ if ($action == 'create') {
 
 					print "</tr>\n";
 
+					$colspan = 6;
+					if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
+						$colspan++;
+					}
+					if (isModEnabled('margin') && !empty($conf->global->MARGIN_SHOW_ON_CONTRACT)) {
+						$colspan++;
+					}
+
 					// Dates of service planed and real
 					if ($objp->subprice >= 0) {
-						$colspan = 6;
-
-						if (isModEnabled('margin') && getDolGlobalString('PRODUCT_USE_UNITS')) {
-							$colspan = 8;
-						} elseif (isModEnabled('margin') || getDolGlobalString('PRODUCT_USE_UNITS')) {
-							$colspan = 7;
-						}
-
 						print '<tr class="oddeven" '.$moreparam.'>';
 						print '<td colspan="'.$colspan.'">';
 
@@ -1832,8 +1835,17 @@ if ($action == 'create') {
 				if (!empty($conf->global->CONTRACT_HIDE_CLOSED_SERVICES_BY_DEFAULT) && $object->lines[$cursorline - 1]->statut == ContratLigne::STATUS_CLOSED && $action != 'showclosedlines') {
 					$moreparam = 'style="display: none;"';
 				}
+
+				$colspan = 6;
+				if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
+					$colspan++;
+				}
+				if (isModEnabled('margin') && !empty($conf->global->MARGIN_SHOW_ON_CONTRACT)) {
+					$colspan++;
+				}
+
 				print '<tr class="oddeven" '.$moreparam.'>';
-				print '<td class="tdhrthin" colspan="'.(isModEnabled('margin') ? 7 : 6).'"><hr class="opacitymedium tdhrthin"></td>';
+				print '<td class="tdhrthin" colspan="'.$colspan.'"><hr class="opacitymedium tdhrthin"></td>';
 				print "</tr>\n";
 			}
 

+ 3 - 3
htdocs/core/actions_linkedfiles.inc.php

@@ -96,7 +96,7 @@ if (GETPOST('sendit', 'alpha') && !empty($conf->global->MAIN_UPLOAD_DOC) && !emp
 		// Parse $newUrl
 		$newUrlArray = parse_url($link);
 
-		// Check URL is external
+		// Allow external links to svg ?
 		if (!getDolGlobalString('MAIN_ALLOW_SVG_FILES_AS_EXTERNAL_LINKS')) {
 			if (!empty($newUrlArray['path']) && preg_match('/\.svg$/i', $newUrlArray['path'])) {
 				$error++;
@@ -104,9 +104,9 @@ if (GETPOST('sendit', 'alpha') && !empty($conf->global->MAIN_UPLOAD_DOC) && !emp
 				setEventMessages($langs->trans('ErrorSVGFilesNotAllowedAsLinksWithout', 'MAIN_ALLOW_SVG_FILES_AS_EXTERNAL_LINKS'), null, 'errors');
 			}
 		}
-		// Alow external links to svg ?
+		// Check URL is external (must refuse local link by default)
 		if (!getDolGlobalString('MAIN_ALLOW_LOCAL_LINKS_AS_EXTERNAL_LINKS')) {
-			// Test $newUrlAray['host'] to check link is external using isIPAllowed()
+			// Test $newUrlAray['host'] to check link is external using isIPAllowed() and if not refuse the local link
 			// TODO
 		}
 

+ 4 - 5
htdocs/core/lib/functions.lib.php

@@ -955,8 +955,6 @@ function checkVal($out = '', $check = 'alphanohtml', $filter = null, $options =
  */
 function sanitizeVal($out = '', $check = 'alphanohtml', $filter = null, $options = null)
 {
-	global $conf;
-
 	// TODO : use class "Validate" to perform tests (and add missing tests) if needed for factorize
 	// Check is done after replacement
 	switch ($check) {
@@ -1044,8 +1042,9 @@ function sanitizeVal($out = '', $check = 'alphanohtml', $filter = null, $options
 		case 'nohtml':		// No html
 			$out = dol_string_nohtmltag($out, 0);
 			break;
-		case 'restricthtml':		// Recommended for most html textarea
 		case 'restricthtmlnolink':
+		case 'restricthtml':		// Recommended for most html textarea
+		case 'restricthtmlallowclass':
 		case 'restricthtmlallowunvalid':
 			$out = dol_htmlwithnojs($out, 1, $check);
 			break;
@@ -7356,7 +7355,7 @@ function dol_nl2br($stringtoencode, $nl2brmode = 0, $forxml = false)
  *
  * @param	string	$stringtoencode				String to encode
  * @param	int     $nouseofiframesandbox		Allow use of option MAIN_SECURITY_USE_SANDBOX_FOR_HTMLWITHNOJS for html sanitizing
- * @param	string	$check						'restricthtmlnolink' or 'restricthtml' or 'restricthtmlallowunvalid'
+ * @param	string	$check						'restricthtmlnolink' or 'restricthtml' or 'restricthtmlallowclass' or 'restricthtmlallowunvalid'
  * @return	string								HTML sanitized
  */
 function dol_htmlwithnojs($stringtoencode, $nouseofiframesandbox = 0, $check = 'restricthtml')
@@ -7415,7 +7414,7 @@ function dol_htmlwithnojs($stringtoencode, $nouseofiframesandbox = 0, $check = '
 			$out = preg_replace('/&#x?[0-9]+/i', '', $out);	// For example if we have j&#x61vascript with an entities without the ; to hide the 'a' of 'javascript'.
 
 			// Keep only some html tags and remove also some 'javascript:' strings
-			$out = dol_string_onlythesehtmltags($out, 0, 1, 1);
+			$out = dol_string_onlythesehtmltags($out, 0, ($check == 'restricthtmlallowclass' ? 0 : 1), 1);
 
 			// We should also exclude non expected HTML attributes and clean content of some attributes (keep only alt=, title=...).
 			if (!empty($conf->global->MAIN_RESTRICTHTML_REMOVE_ALSO_BAD_ATTRIBUTES)) {

+ 1 - 1
htdocs/core/lib/website.lib.php

@@ -760,7 +760,7 @@ function getStructuredData($type, $data = array())
 			$ret .= "\n".'}'."\n";
 			$ret .= '</script>'."\n";
 		} else {
-			$ret .= '<!-- no structured data inserted inline inside blogpost because no author_alias defined -->'."\n";
+			$ret = '<!-- no structured data inserted inline inside blogpost because no author_alias defined -->'."\n";
 		}
 	} elseif ($type == 'product') {
 		$ret = '<!-- Add structured data for product -->'."\n";

+ 12 - 2
htdocs/core/menus/standard/eldy.lib.php

@@ -986,7 +986,14 @@ function print_left_eldy_menu($db, $menu_array_before, $menu_array_after, &$tabM
 					} else {
 						print '<span class="vmenu">';
 					}
-					print ($menu_array[$i]['prefix'] ? $menu_array[$i]['prefix'] : '').$menu_array[$i]['titre'];
+					if (!empty($menu_array[$i]['prefix'])) {
+						if (preg_match('/^fa-[a-zA-Z0-9-_]+$/', $menu_array[$i]['prefix'])) {
+							print '<span class="fa '.$menu_array[$i]['prefix'].' paddingright pictofixedwidth"></span>';
+						} else {
+							print $menu_array[$i]['prefix'];
+						}
+					}
+					print $menu_array[$i]['titre'];
 					if ($shorturlwithoutparam) {
 						print '</a>';
 					} else {
@@ -997,7 +1004,10 @@ function print_left_eldy_menu($db, $menu_array_before, $menu_array_after, &$tabM
 				} elseif ($showmenu) {                 // Not enabled but visible (so greyed)
 					print '<div class="menu_titre">'.$tabstring;
 					print '<span class="vmenudisabled">';
-					print ($menu_array[$i]['prefix'] ? $menu_array[$i]['prefix'] : '').$menu_array[$i]['titre'];
+					if (!empty($menu_array[$i]['prefix'])) {
+						print $menu_array[$i]['prefix'];
+					}
+					print $menu_array[$i]['titre'];
 					print '</span>';
 					print '</div>'."\n";
 					$lastlevel0 = 'greyed';

+ 24 - 22
htdocs/core/modules/DolibarrModules.class.php

@@ -2430,7 +2430,7 @@ class DolibarrModules // Can not be abstract, because we need to instantiate it
 			$versiontrans .= 'warning';
 		}
 
-		print '
+		$return = '
     	<div class="box-flex-item info-box-module'
 			.(empty($conf->global->$const_name) ? ' --disabled' : '')
 			.($this->isCoreOrExternalModule() == 'external' ? ' --external' : '')
@@ -2444,12 +2444,12 @@ class DolibarrModules // Can not be abstract, because we need to instantiate it
 		//if (is_array($objMod->phpmin)) $alttext.=($alttext?' - ':'').'PHP >= '.join('.',$objMod->phpmin);
 		if (!empty($this->picto)) {
 			if (preg_match('/^\//i', $this->picto)) {
-				print img_picto($alttext, $this->picto, 'class="inline-block valignmiddle"', 1);
+				$return .= img_picto($alttext, $this->picto, 'class="inline-block valignmiddle"', 1);
 			} else {
-				print img_object($alttext, $this->picto, 'class="inline-block valignmiddle"');
+				$return .= img_object($alttext, $this->picto, 'class="inline-block valignmiddle"');
 			}
 		} else {
-			print img_object($alttext, 'generic', 'class="inline-block valignmiddle"');
+			$return .= img_object($alttext, 'generic', 'class="inline-block valignmiddle"');
 		}
 
 		if ($this->isCoreOrExternalModule() == 'external' || preg_match('/development|experimental|deprecated/i', $version)) {
@@ -2458,34 +2458,36 @@ class DolibarrModules // Can not be abstract, because we need to instantiate it
 				$versionTitle.= '<br>'.$langs->trans('ModuleUpdateAvailable').' : '.$this->lastVersion;
 			}
 
-			print '<span class="info-box-icon-version'.($versiontrans ? ' '.$versiontrans : '').' classfortooltip" title="'.dol_escape_js($versionTitle).'" >';
-			print $this->getVersion(1);
-			print '</span>';
+			$return .=  '<span class="info-box-icon-version'.($versiontrans ? ' '.$versiontrans : '').' classfortooltip" title="'.dol_escape_js($versionTitle).'" >';
+			$return .=  $this->getVersion(1);
+			$return .=  '</span>';
 		}
 
-		print '</div>
+		$return .=  '</div>
 	    <div class="info-box-content info-box-text-module'.(empty($conf->global->$const_name) ? '' : ' info-box-module-enabled'.($versiontrans ? ' info-box-content-warning' : '')).'">
 	    <span class="info-box-title">'.$this->getName().'</span>
 	    <span class="info-box-desc twolinesmax opacitymedium" title="'.dol_escape_htmltag($this->getDesc()).'">'.nl2br($this->getDesc()).'</span>';
 
-		print '<div class="valignmiddle inline-block info-box-more">';
+		$return .=  '<div class="valignmiddle inline-block info-box-more">';
 		//if ($versiontrans) print img_warning($langs->trans("Version").' '.$this->getVersion(1)).' ';
-		print '<a class="valignmiddle inline-block" href="javascript:document_preview(\''.DOL_URL_ROOT.'/admin/modulehelp.php?id='.$this->numero.'\',\'text/html\',\''.dol_escape_js($langs->trans("Module")).'\')">'.img_picto(($this->isCoreOrExternalModule() == 'external' ? $langs->trans("ExternalModule").' - ' : '').$langs->trans("ClickToShowDescription"), $imginfo).'</a>';
-		print '</div><br>';
-
-		print '<div class="valignmiddle inline-block info-box-actions">';
-		print '<div class="valignmiddle inline-block info-box-setup">';
-		print $codetoconfig;
-		print '</div>';
-		print '<div class="valignmiddle inline-block marginleftonly marginrightonly">';
-		print $codeenabledisable;
-		print '</div>';
-		print '</div>';
-
-		print '
+		$return .=  '<a class="valignmiddle inline-block" href="javascript:document_preview(\''.DOL_URL_ROOT.'/admin/modulehelp.php?id='.$this->numero.'\',\'text/html\',\''.dol_escape_js($langs->trans("Module")).'\')">'.img_picto(($this->isCoreOrExternalModule() == 'external' ? $langs->trans("ExternalModule").' - ' : '').$langs->trans("ClickToShowDescription"), $imginfo).'</a>';
+		$return .=  '</div><br>';
+
+		$return .=  '<div class="valignmiddle inline-block info-box-actions">';
+		$return .=  '<div class="valignmiddle inline-block info-box-setup">';
+		$return .=  $codetoconfig;
+		$return .=  '</div>';
+		$return .=  '<div class="valignmiddle inline-block marginleftonly marginrightonly">';
+		$return .=  $codeenabledisable;
+		$return .=  '</div>';
+		$return .=  '</div>';
+
+		$return .=  '
 	    </div><!-- /.info-box-content -->
 	    </div><!-- /.info-box -->
 	    </div>';
+
+		return $return;
 	}
 
 	/**

+ 1 - 1
htdocs/fichinter/card-rec.php

@@ -581,7 +581,7 @@ if ($action == 'create') {
 				print '</tr></table>';
 				print '</td><td>';
 				if ($action == 'contrat') {
-					$formcontract = new Formcontract($db);
+					$formcontract = new FormContract($db);
 					$formcontract->formSelectContract($_SERVER["PHP_SELF"].'?id='.$object->id, $object->socid, $object->fk_contrat, 'contratid', 0, 1);
 				} else {
 					if ($object->fk_contrat) {

+ 1 - 1
htdocs/fichinter/card.php

@@ -1248,7 +1248,7 @@ if ($action == 'create') {
 		print '</tr></table>';
 		print '</td><td>';
 		if ($action == 'contrat') {
-			$formcontract = new Formcontract($db);
+			$formcontract = new FormContract($db);
 			$formcontract->formSelectContract($_SERVER["PHP_SELF"].'?id='.$object->id, $object->socid, $object->fk_contrat, 'contratid', 0, 1, 1);
 		} else {
 			if ($object->fk_contrat) {

+ 1 - 1
htdocs/install/mysql/tables/llx_menu.sql

@@ -36,7 +36,7 @@ CREATE TABLE llx_menu
 	url           varchar(255) NOT NULL,					-- Relative (or absolute) url to go
 	target        varchar(100) NULL,						-- Target of Url link
 	titre         varchar(255) NOT NULL,					-- Key for menu translation
-	prefix        varchar(255) NULL,					    -- prefix
+	prefix        varchar(255) NULL,					    -- picto
 	langs         varchar(100),								-- Lang file to load for translation
 	level         smallint,									-- Deprecated. Not used.
 	perms         text,										-- Condition to show enabled or disabled

+ 1 - 1
htdocs/langs/en_US/dict.lang

@@ -137,7 +137,7 @@ CountryLV=Latvia
 CountryLB=Lebanon
 CountryLS=Lesotho
 CountryLR=Liberia
-CountryLY=Libyan
+CountryLY=Libya
 CountryLI=Liechtenstein
 CountryLT=Lithuania
 CountryLU=Luxembourg

+ 2 - 0
htdocs/societe/class/societeaccount.class.php

@@ -534,6 +534,8 @@ class SocieteAccount extends CommonObject
 				return $langs->trans('Disabled').' '.img_picto($langs->trans('Disabled'), 'statut5');
 			}
 		}
+
+		return '';
 	}
 
 	/**

+ 1 - 1
htdocs/theme/eldy/global.inc.php

@@ -2532,7 +2532,7 @@ img.photorefnoborder {
 }
 
 .tdhrthin {
-	margin: 0;
+	margin: 0 !important;
 	padding-bottom: 0 !important;
 }
 

+ 1 - 1
htdocs/theme/md/style.css.php

@@ -2706,7 +2706,7 @@ img.photorefnoborder {
 	border-bottom: 1px solid var(--colortopbordertitle1) !important;
 }
 .tdhrthin {
-	margin: 0;
+	margin: 0 !important;
 	padding-bottom: 0 !important;
 }
 /* Payment Screen : Pointer cursor in the autofill image */