From 3c5a0c862f834b791d6ac020a26f1d3d401bb34f Mon Sep 17 00:00:00 2001 From: Lucas Werkmeister Date: Thu, 13 Jul 2023 17:44:35 +0200 Subject: Html: Move encodeJsVar() + encodeJsCall() from Xml These methods really belong in the Html class, not Xml. Leave behind soft-deprecated Xml methods that forward to the Html ones, as well as a class alias for HtmlJsCode (renamed from XmlJsCode). Bug: T341779 Change-Id: I99a5f9de1411d4eb5ee30226b4e8ace3ea8b2c3b --- includes/Html/Html.php | 45 ++++++++++++++++++++++++ includes/Html/HtmlJsCode.php | 81 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 126 insertions(+) create mode 100644 includes/Html/HtmlJsCode.php (limited to 'includes/Html') diff --git a/includes/Html/Html.php b/includes/Html/Html.php index ceb85f2a5ff0..e4f145b8802f 100644 --- a/includes/Html/Html.php +++ b/includes/Html/Html.php @@ -25,6 +25,7 @@ namespace MediaWiki\Html; +use FormatJson; use InvalidArgumentException; use MediaWiki\MainConfigNames; use MediaWiki\MediaWikiServices; @@ -1149,6 +1150,50 @@ class Html { return implode( ", ", $candidates ); } + + /** + * Encode a variable of arbitrary type to JavaScript. + * If the value is an HtmlJsCode object, pass through the object's value verbatim. + * + * @note Only use this function for generating JavaScript code. If generating output + * for a proper JSON parser, just call FormatJson::encode() directly. + * + * @since 1.41 (previously on {@link Xml}) + * @param mixed $value The value being encoded. Can be any type except a resource. + * @param bool $pretty If true, add non-significant whitespace to improve readability. + * @return string|false String if successful; false upon failure + */ + public static function encodeJsVar( $value, $pretty = false ) { + if ( $value instanceof HtmlJsCode ) { + return $value->value; + } + return FormatJson::encode( $value, $pretty, FormatJson::UTF8_OK ); + } + + /** + * Create a call to a JavaScript function. The supplied arguments will be + * encoded using Html::encodeJsVar(). + * + * @since 1.41 (previously on {@link Xml} since 1.17) + * @param string $name The name of the function to call, or a JavaScript expression + * which evaluates to a function object which is called. + * @param array $args The arguments to pass to the function. + * @param bool $pretty If true, add non-significant whitespace to improve readability. + * @return string|false String if successful; false upon failure + */ + public static function encodeJsCall( $name, $args, $pretty = false ) { + foreach ( $args as &$arg ) { + $arg = self::encodeJsVar( $arg, $pretty ); + if ( $arg === false ) { + return false; + } + } + + return "$name(" . ( $pretty + ? ( ' ' . implode( ', ', $args ) . ' ' ) + : implode( ',', $args ) + ) . ");"; + } } class_alias( Html::class, 'Html' ); diff --git a/includes/Html/HtmlJsCode.php b/includes/Html/HtmlJsCode.php new file mode 100644 index 000000000000..e857237f3902 --- /dev/null +++ b/includes/Html/HtmlJsCode.php @@ -0,0 +1,81 @@ +value = $value; + } + + /** + * Encode an object containing HtmlJsCode objects. + * + * This takes an object or associative array where (some of) the values are HtmlJsCode objects, + * and re-encodes it as a single HtmlJsCode object. + * + * @since 1.33 + * @phpcs:ignore MediaWiki.Commenting.FunctionComment.ObjectTypeHintParam + * @param object|array $obj Object or associative array to encode + * @param bool $pretty If true, add non-significant whitespace to improve readability. + * @return HtmlJsCode + */ + public static function encodeObject( $obj, $pretty = false ) { + $parts = []; + foreach ( $obj as $key => $value ) { + $parts[] = + ( $pretty ? ' ' : '' ) . + Html::encodeJsVar( $key, $pretty ) . + ( $pretty ? ': ' : ':' ) . + Html::encodeJsVar( $value, $pretty ); + } + return new self( + '{' . + ( $pretty ? "\n" : '' ) . + implode( $pretty ? ",\n" : ',', $parts ) . + ( $pretty ? "\n" : '' ) . + '}' + ); + } +} + +/** @deprecated since 1.41 */ +class_alias( HtmlJsCode::class, 'XmlJsCode' ); -- cgit v1.2.3