diff options
author | Lucas Werkmeister <lucas.werkmeister@wikimedia.de> | 2023-07-13 17:44:35 +0200 |
---|---|---|
committer | James D. Forrester <jforrester@wikimedia.org> | 2023-07-14 13:42:02 -0400 |
commit | 3c5a0c862f834b791d6ac020a26f1d3d401bb34f (patch) | |
tree | f737f7adaa05cebfcf897e18c91631ba3cfd9894 /includes/Html | |
parent | b45e48b35c04c93c9c1cf70b76ac92b0cbf713ea (diff) | |
download | mediawikicore-3c5a0c862f834b791d6ac020a26f1d3d401bb34f.tar.gz mediawikicore-3c5a0c862f834b791d6ac020a26f1d3d401bb34f.zip |
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
Diffstat (limited to 'includes/Html')
-rw-r--r-- | includes/Html/Html.php | 45 | ||||
-rw-r--r-- | includes/Html/HtmlJsCode.php | 81 |
2 files changed, 126 insertions, 0 deletions
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 @@ +<?php +/** + * 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 2 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, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * http://www.gnu.org/copyleft/gpl.html + * + * @file + */ + +namespace MediaWiki\Html; + +/** + * A wrapper class which causes Html::encodeJsVar() and Html::encodeJsCall() + * (as well as their Xml::* counterparts) to interpret a given string as being + * a JavaScript expression, instead of string data. + * + * @par Example: + * @code + * Html::encodeJsVar( new HtmlJsCode( 'a + b' ) ); + * @endcode + * + * This returns "a + b". + * + * @note As of 1.21, HtmlJsCode objects cannot be nested inside objects or arrays. The sole + * exception is the $args argument to Html::encodeJsCall() because Html::encodeJsVar() is + * called for each individual element in that array. If you need to encode an object or array + * containing HtmlJsCode objects, use HtmlJsCode::encodeObject() to re-encode it first. + * + * @since 1.41 (renamed from XmlJsCode, which existed since 1.17) + */ +class HtmlJsCode { + public $value; + + public function __construct( $value ) { + $this->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' ); |