diff --git a/htdocs/categories/class/categorie.class.php b/htdocs/categories/class/categorie.class.php index 6e1b9083210..08a680c1e1b 100644 --- a/htdocs/categories/class/categorie.class.php +++ b/htdocs/categories/class/categorie.class.php @@ -1466,12 +1466,13 @@ class Categorie extends CommonObject // phpcs:enable $ways = array(); - $all_ways = $this->get_all_ways(); // Load array of categories - foreach ($all_ways as $way) { + $all_ways = $this->get_all_ways(); // Load array of categories to reach this->id + + foreach ($all_ways as $way) { // It seems we always have 1 entry in this array. $w = array(); $i = 0; $forced_color = ''; - foreach ($way as $cat) { + foreach ($way as $cat) { // Loop on each successive categories to reach the target of current category $i++; if (empty($nocolor)) { @@ -1511,6 +1512,7 @@ class Categorie extends CommonObject // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Returns an array containing the list of parent categories + * Note: A category can only have one parent but this method return an array to work the same way the get_filles is working. * * @return int|Categorie[] Return integer <0 KO, array OK */ @@ -1541,7 +1543,7 @@ class Categorie extends CommonObject // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** - * Returns in a table all possible paths to get to the category + * Returns in a array all possible paths to go to the category * starting with the major categories represented by Tables of categories * * @return Categorie[][] @@ -1554,7 +1556,7 @@ class Categorie extends CommonObject $parents = $this->get_meres(); if (is_array($parents)) { foreach ($parents as $parent) { - $all_ways = $parent->get_all_ways(); + $all_ways = $parent->get_all_ways(); // recursivity. TODO Add a protection for infinite loop foreach ($all_ways as $way) { $w = $way; $w[] = $this; @@ -1646,8 +1648,8 @@ class Categorie extends CommonObject } /** - * Returns categories whose id or name match - * add wildcards in the name unless $exact = true + * Returns categories whose id or name matches. + * It add wildcards in the name unless $exact = true * * @param int $id Id * @param string $nom Name diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index e436c45cfb5..868815a49b8 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -2015,12 +2015,13 @@ function dol_escape_xml($stringtoescape) * Return a string label (so on 1 line only and that should not contains any HTML) ready to be output on HTML page. * To use text that is not HTML content inside an attribute, you can simply use only dol_escape_htmltag(). In doubt, use dolPrintHTMLForAttribute(). * - * @param string $s String to print - * @return string String ready for HTML output + * @param string $s String to print + * @param int $escapeonlyhtmltags 1=Escape only html tags, not the special chars like accents. + * @return string String ready for HTML output */ -function dolPrintLabel($s) +function dolPrintLabel($s, $escapeonlyhtmltags = 0) { - return dol_escape_htmltag(dol_string_nohtmltag($s, 1, 'UTF-8', 0, 0), 0, 0, '', 0, 1); + return dol_escape_htmltag(dol_string_nohtmltag($s, 1, 'UTF-8', 0, 0), 0, 0, '', $escapeonlyhtmltags, 1); } /** @@ -2051,18 +2052,23 @@ function dolPrintHTML($s, $allowiframe = 0) } /** - * Return a string ready to be output on an HTML attribute (alt, title, data-html, ...) + * Return a string ready to be output into an HTML attribute (alt, title, data-html, ...) * With dolPrintHTMLForAttribute(), the content is HTML encode, even if it is already HTML content. * - * @param string $s String to print - * @return string String ready for HTML output + * @param string $s String to print + * @param int $escapeonlyhtmltags 1=Escape only html tags, not the special chars like accents. + * @return string String ready for HTML output * @see dolPrintHTML(), dolPrintHTMLFortextArea() */ -function dolPrintHTMLForAttribute($s) +function dolPrintHTMLForAttribute($s, $escapeonlyhtmltags = 0) { - // The dol_htmlentitiesbr will convert simple text into html - // The dol_escape_htmltag will escape html chars. - return dol_escape_htmltag(dol_string_onlythesehtmltags(dol_htmlentitiesbr($s), 1, 0, 0, 0, array('br', 'b', 'font', 'hr', 'span')), 1, -1, '', 0, 1); + // The dol_htmlentitiesbr will convert simple text into html, including switching accent into HTML entities + // The dol_escape_htmltag will escape html tags. + if ($escapeonlyhtmltags) { + return dol_escape_htmltag(dol_string_onlythesehtmltags($s, 1, 0, 0, 0, array('br', 'b', 'font', 'hr', 'span')), 1, -1, '', 1, 1); + } else { + return dol_escape_htmltag(dol_string_onlythesehtmltags(dol_htmlentitiesbr($s), 1, 0, 0, 0, array('br', 'b', 'font', 'hr', 'span')), 1, -1, '', 0, 1); + } } /** diff --git a/htdocs/core/lib/website.lib.php b/htdocs/core/lib/website.lib.php index c9cbbb6dafa..697d3f5674d 100644 --- a/htdocs/core/lib/website.lib.php +++ b/htdocs/core/lib/website.lib.php @@ -509,14 +509,15 @@ function dolWebsiteSaveContent($content) /** * Make a redirect to another container. * - * @param string $containerref Ref of container to redirect to (Example: 'mypage' or 'mypage.php'). - * @param string $containeraliasalt Ref of alternative aliases to redirect to. - * @param int $containerid Id of container. - * @param int<0,1> $permanent 0=Use temporary redirect 302, 1=Use permanent redirect 301 - * @param array $parameters Array of parameters to append to the URL. + * @param string $containerref Ref of container to redirect to (Example: 'mypage' or 'mypage.php'). + * @param string $containeraliasalt Ref of alternative aliases to redirect to. + * @param int $containerid Id of container. + * @param int<0,1> $permanent 0=Use temporary redirect 302 (default), 1=Use permanent redirect 301 + * @param array $parameters Array of parameters to append to the URL. + * @param int<0,1> $parampropagation 0=Do not propagate query parameter in URL when doing the redirect, 1=Keep parameters (default) * @return void */ -function redirectToContainer($containerref, $containeraliasalt = '', $containerid = 0, $permanent = 0, $parameters = array()) +function redirectToContainer($containerref, $containeraliasalt = '', $containerid = 0, $permanent = 0, $parameters = array(), $parampropagation = 1) { global $db, $website; '@phan-var-force Website $website'; @@ -572,7 +573,9 @@ function redirectToContainer($containerref, $containeraliasalt = '', $containeri } } else { // When page called from virtual host server $newurl = '/'.$containerref.'.php'; - $newurl .= (empty($_SERVER["QUERY_STRING"]) ? '' : '?'.$_SERVER["QUERY_STRING"]); + if ($parampropagation) { + $newurl .= (empty($_SERVER["QUERY_STRING"]) ? '' : '?'.$_SERVER["QUERY_STRING"]); + } } if ($newurl) { diff --git a/htdocs/core/lib/website2.lib.php b/htdocs/core/lib/website2.lib.php index fb161162679..5438789e826 100644 --- a/htdocs/core/lib/website2.lib.php +++ b/htdocs/core/lib/website2.lib.php @@ -215,17 +215,17 @@ function dolSavePageContent($filetpl, Website $object, WebsitePage $objectpage, $canonicalurladdidlang = ''; if ($objectpage->lang) { // A language is forced on the page, it means we may have other language files with hard links into properties of page $canonicalurl = (($objectpage->id == $object->fk_default_home) ? '/' : (($shortlangcode != substr($object->lang, 0, 2) ? '/'.$shortlangcode : '').'/'.$objectpage->pageurl.'.php')); - } else { // No language forced, it means the canonical is the one with + } else { // No language forced, it means the canonical is the one with params making url unique $canonicalurl = '/'.$objectpage->pageurl.'.php'; if ($object->lang && $listofaltlang) { $tmpshortlangcode = preg_replace('/[_-].*$/', '', $object->lang); // en_US or en-US -> en // Add parameter ID required to be unique/canonical - $canonicalurladdidlang = ''; - $canonicalurladdidlang .= 'l=shortlang ? $weblangs->shortlang : "'.$tmpshortlangcode.'"; ?>'; + $canonicalurladdidlang = '?__SEO_CANONICAL_URL_PARAMS__'; + $canonicalurladdidlang .= '&l=shortlang ? $weblangs->shortlang : "'.$tmpshortlangcode.'"; ?>'; } else { // Add parameter ID required to be unique/canonical - $canonicalurladdidlang = ''; + $canonicalurladdidlang = '?__SEO_CANONICAL_URL_PARAMS__'; } } @@ -278,20 +278,20 @@ function dolSavePageContent($filetpl, Website $object, WebsitePage $objectpage, $tplcontent .= ''."\n"; $tplcontent .= ''."\n"; - } else { + } else { // No language forced, it means the canonical is the one withparams making url unique $canonicalurl = '/'.$objectpage->pageurl.'.php'; $arrayofaltlang = explode(',', $listofaltlang); foreach ($arrayofaltlang as $altlang) { // Add parameter ID required to be unique/canonical - $canonicalurladdidlang = ''; - $canonicalurladdidlang .= 'l='.$altlang; + $canonicalurladdidlang = '?__SEO_CANONICAL_URL_PARAMS__'; + $canonicalurladdidlang .= '&l='.$altlang; $tplcontent .= ''."\n"; } $tmpshortlangcode = preg_replace('/[_-].*$/', '', $object->lang); // en_US or en-US -> en - $canonicalurladdidlang = ''; - $canonicalurladdidlang .= 'l='.$tmpshortlangcode; + $canonicalurladdidlang = '?__SEO_CANONICAL_URL_PARAMS__'; + $canonicalurladdidlang .= '&l='.$tmpshortlangcode; $tplcontent .= ''."\n"; } } @@ -320,29 +320,34 @@ function dolSavePageContent($filetpl, Website $object, WebsitePage $objectpage, $tplcontent .= 'content, '$__PAGE__TITLE__') !== false) { - $tplcontent .= '$tmp = preg_replace("/.*?<\/title>/s", "<title>" . dol_escape_htmltag($__PAGE__TITLE__) . "", $tmp);'."\n"; - $tplcontent .= '$tmp = preg_replace("//s", "", $tmp);'; - } if (strpos($objectpage->content, '$__PAGE__KEYWORDS__') !== false) { - $tplcontent .= '$tmp = preg_replace("//s", "", $tmp);'; + $tplcontent .= '$tmp = preg_replace("/^/ms", "", $tmp);'."\n"; + } + if (strpos($objectpage->content, '$__PAGE__TITLE__') !== false) { + $tplcontent .= '$tmp = preg_replace("/^.*?<\/title>/ms", "<title>" . dolPrintHTMLForAttribute($__PAGE__TITLE__, 1) . "", $tmp);'."\n"; + $tplcontent .= '$tmp = preg_replace("/^/ms", "", $tmp);'."\n"; } if (strpos($objectpage->content, '$__PAGE__DESC__') !== false) { - $tplcontent .= '$tmp = preg_replace("//s", "", $tmp);'; + $tplcontent .= '$tmp = preg_replace("/^/ms", "", $tmp);'."\n"; } // New method for custom SEO - if (strpos($objectpage->content, 'define("__SEO_PAGE_TITLE__"') !== false) { - $tplcontent .= '$tmp = preg_replace("/.*?<\/title>/s", "<title>" . dol_escape_htmltag(constant("__SEO_PAGE_TITLE__")) . "", $tmp);'."\n"; - $tplcontent .= '$tmp = preg_replace("//s", "", $tmp);'; - } if (strpos($objectpage->content, 'define("__SEO_PAGE_KEYWORDS__"') !== false) { - $tplcontent .= '$tmp = preg_replace("//s", "", $tmp);'; + $tplcontent .= '$tmp = preg_replace("/^/ms", "", $tmp);'."\n"; + } + if (strpos($objectpage->content, 'define("__SEO_PAGE_TITLE__"') !== false) { + $tplcontent .= '$tmp = preg_replace("/^.*?<\/title>/ms", "<title>" . dolPrintHTMLForAttribute(constant("__SEO_PAGE_TITLE__"), 1) . "", $tmp);'."\n"; + $tplcontent .= '$tmp = preg_replace("/^/ms", "", $tmp);'."\n"; } if (strpos($objectpage->content, 'define("__SEO_PAGE_DESC__"') !== false) { - $tplcontent .= '$tmp = preg_replace("//s", "", $tmp);'; + $tplcontent .= '$tmp = preg_replace("/^/ms", "", $tmp);'."\n"; + } + if (empty($objectpage->lang)) { // We may need to use param into the canonical url + $tplcontent .= 'defined("__SEO_CANONICAL_URL_PARAMS__") ? ($tmp = preg_replace("/__SEO_CANONICAL_URL_PARAMS__/", dolPrintHTMLForAttributeUrl(constant("__SEO_CANONICAL_URL_PARAMS__")), $tmp)) : ($tmp = preg_replace("/\?__SEO_CANONICAL_URL_PARAMS__\"/", "", preg_replace("/\?__SEO_CANONICAL_URL_PARAMS__&/", "?", $tmp)));'."\n"; } + $tplcontent .= "// Now output the generated page content\n"; $tplcontent .= 'dolWebsiteOutput($tmp, "html", '.((int) $objectpage->id).'); dolWebsiteIncrementCounter('.((int) $object->id).', "'.$objectpage->type_container.'", '.((int) $objectpage->id).');'."\n"; $tplcontent .= "// END PHP ?>\n"; } else {