... * to * "<script>...</hello>" * * * @param $text * @return string * * Note that if the `meta[charset]` matches the text encoding , it should not be encoded * * True ? Beware that this still allows users to insert unsafe scripting vectors, such as markdown links like [xss](javascript:alert%281%29). */ public static function encode($text): string { /** * See https://stackoverflow.com/questions/46483/htmlentities-vs-htmlspecialchars/3614344 * * Not {@link htmlentities } htmlentities($text, ENT_QUOTES); * Otherwise we get `Error while loading HTMLError: Entity 'hellip' not defined` * when loading HTML with {@link XmlDocument} * * See also {@link self::htmlDecode()} * * Without ENT_QUOTES *

* is encoded as * >h4 class="heading-combo"< * and cannot be added in a attribute because of the quote * This is used for {@link Tooltip} */ return htmlspecialchars($text, ENT_XHTML | ENT_QUOTES | ENT_DISALLOWED); } public static function decode($int): string { return htmlspecialchars_decode($int, ENT_XHTML | ENT_QUOTES); } public static function getDiffBetweenValuesSeparatedByBlank(string $expected, string $actual, string $expectedName = "expected class", string $actualName = "actual class"): string { $leftClasses = preg_split("/\s/", $expected); $rightClasses = preg_split("/\s/", $actual); $error = ""; foreach ($leftClasses as $leftClass) { if (!in_array($leftClass, $rightClasses)) { $error .= "The $expectedName has the value (" . $leftClass . ") that is not present in the $actualName)\n"; } else { // Delete the value $key = array_search($leftClass, $rightClasses); unset($rightClasses[$key]); } } foreach ($rightClasses as $rightClass) { $error .= "The $actualName has the value (" . $rightClass . ") that is not present in the $expectedName)\n"; } return $error; } /** * @throws ExceptionBadSyntax - bad url * @throws ExceptionNotEquals - not equals */ public static function getDiffBetweenSrcSet(string $expected, string $actual) { $expectedSrcSets = explode(",", $expected); $actualSrcSets = explode(",", $actual); $countExpected = count($expectedSrcSets); $countActual = count($actualSrcSets); if ($countExpected !== $countActual) { throw new ExceptionNotEquals("The expected srcSet count ($countExpected) is not the same than the actual ($countActual)."); } for ($i = 0; $i < $countExpected; $i++) { $expectedSrcSet = trim($expectedSrcSets[$i]); $expectedSrcSetExploded = explode(" ", $expectedSrcSet, 2); $expectedSrc = $expectedSrcSetExploded[0]; if (count($expectedSrcSetExploded) == 2) { $expectedWidth = $expectedSrcSetExploded[1]; } else { $expectedWidth = null; } $actualSrcSet = trim($actualSrcSets[$i]); $actualSrcSetExploded = explode(" ", $actualSrcSet, 2); $actualSrc = $actualSrcSetExploded[0]; if (count($actualSrcSetExploded) == 2) { $actualWidth = $actualSrcSetExploded[1]; } else { $actualWidth = null; } if ($expectedWidth !== $actualWidth) { throw new ExceptionNotEquals("The expected width ($expectedWidth) of the srcSet ($i) is not the same than the actual ($actualWidth)."); } try { Html::getDiffBetweenUrlStrings($expectedSrc, $actualSrc); } catch (ExceptionBadSyntax $e) { throw new ExceptionBadSyntax("Bad Syntax on Src Set ($i). Error: {$e->getMessage()}. Expected: $expectedSrc vs Actual: $actualSrc. "); } catch (ExceptionNotEquals $e) { throw ExceptionNotEquals::create("Not Equals on Src Set ($i). Error: {$e->getMessage()}.", $expectedSrc, $actualSrc); } } } /** * @throws ExceptionBadSyntax * @throws ExceptionNotEquals */ public static function getDiffBetweenUrlStrings(string $expected, string $actual) { try { $url = Url::createFromString($expected); } catch (ExceptionBadSyntax $e) { throw new ExceptionBadSyntax("The expected URL string ($expected) is not valid. Error: {$e->getMessage()}"); } try { $urlActual = Url::createFromString($actual); } catch (ExceptionBadSyntax $e) { throw new ExceptionBadSyntax("The $actual URL string ($actual) is not valid. Error: {$e->getMessage()}"); } $url->equals($urlActual); } /** * Merge class name * @param string $newNames - the name that we want to add * @param ?string $actualNames - the actual names * @return string - the class name list * * for instance: * * newNames = foo blue * * actual Name = foo bar * return * * foo bar blue */ public static function mergeClassNames(string $newNames, ?string $actualNames): string { /** * It may be in the form "value1 value2" */ $newValues = StringUtility::explodeAndTrim($newNames, " "); if (!empty($actualNames)) { $actualValues = StringUtility::explodeAndTrim(trim($actualNames), " "); } else { $actualValues = []; } $newValues = array_merge($actualValues, $newValues); $newValues = array_unique($newValues); return implode(" ", $newValues); } /** * @param array $styleProperties - an array of CSS properties with key, value * @return string - the value for the style attribute (ie all rules where joined with the comma) */ public static function array2InlineStyle(array $styleProperties) { $inlineCss = ""; foreach ($styleProperties as $key => $value) { $inlineCss .= "$key:$value;"; } // Suppress the last ; if ($inlineCss[strlen($inlineCss) - 1] == ";") { $inlineCss = substr($inlineCss, 0, -1); } return $inlineCss; } }