Index: trunk/extensions/HtmlUi/README |
— | — | @@ -1,3 +1,7 @@ |
| 2 | +== THIS IS EXPERIMENTAL CODE! == |
| 3 | + |
| 4 | +This is an experimental second-coming of the HtmlForm and QuickTemplate classes. |
| 5 | + |
2 | 6 | == General Objective == |
3 | 7 | |
4 | 8 | Provide a managed way to generate HTML user interface components. |
Index: trunk/extensions/HtmlUi/classes/HtmlUiTemplate.php |
— | — | @@ -1,5 +1,15 @@ |
2 | 2 | <?php |
3 | 3 | |
| 4 | +/** |
| 5 | + * Wrapper for a PHP file which contains HTML with embedded PHP tags. |
| 6 | + * |
| 7 | + * Template files wrapped by this class are provided a data-set which is escaped by default. |
| 8 | + * |
| 9 | + * By convention only display logic should be written into templates files and use of the global |
| 10 | + * statement should not be allowed. |
| 11 | + * |
| 12 | + * @author Trevor Parscal <tparscal@wikimedia.org> |
| 13 | + */ |
4 | 14 | class HtmlUiTemplate { |
5 | 15 | |
6 | 16 | /* Protected Members */ |
— | — | @@ -9,8 +19,8 @@ |
10 | 20 | /* Methods */ |
11 | 21 | |
12 | 22 | /** |
13 | | - * @param {string} $file path to template |
14 | | - * @param {array} $data list of properties to initially set |
| 23 | + * @param $file String: path to template |
| 24 | + * @param $data Array: list of properties to initially set |
15 | 25 | */ |
16 | 26 | public function __construct( $filePath ) { |
17 | 27 | if ( !file_exists( $filePath ) ) { |
— | — | @@ -24,12 +34,12 @@ |
25 | 35 | /** |
26 | 36 | * Renders the template using an output-buffer. |
27 | 37 | * |
28 | | - * @param {array} $data List of key/value pairs to expand into variables while rendering |
29 | | - * @return {string} Rendered template |
| 38 | + * @param $data Array: List of key/value pairs to expand into variables while rendering |
| 39 | + * @return String: Rendered template |
30 | 40 | */ |
31 | 41 | public function render( array $data = array() ) { |
32 | | - // Expand bindings to vars, just for this scope |
33 | | - extract( $data ); |
| 42 | + // Expand bindings to vars, just for this scope - escaped by default! |
| 43 | + extract( self::escape( $data ) ); |
34 | 44 | ob_start(); |
35 | 45 | require( $this->filePath ); |
36 | 46 | return ob_get_clean(); |
— | — | @@ -38,28 +48,65 @@ |
39 | 49 | /* Static Methods */ |
40 | 50 | |
41 | 51 | /** |
42 | | - * Escapes a string to be safely rendered in an HTML document. |
| 52 | + * Escapes data to be safely rendered in an HTML document as text (not code). |
| 53 | + * |
| 54 | + * @param $data Mixed: Data to escape, either a string or array of strings |
| 55 | + * @return Mixed: Escaped version of $data |
43 | 56 | */ |
44 | | - public static function escape( $value ) { |
45 | | - // More escaping here may be needed |
46 | | - return htmlspecialchars( $value ); |
| 57 | + public static function escape( $data ) { |
| 58 | + if ( is_array( $data ) ) { |
| 59 | + foreach ( array_keys( $data ) as $key ) { |
| 60 | + $data[$key] = self::escape( $data[$key] ); |
| 61 | + } |
| 62 | + return $data; |
| 63 | + } |
| 64 | + return htmlspecialchars( $data ); |
47 | 65 | } |
48 | 66 | |
49 | 67 | /** |
| 68 | + * Unescapes data to be rendered in an HTML document as HTML (not text). |
| 69 | + * |
| 70 | + * @param $data Mixed: Data to unescape, either a string or array of strings |
| 71 | + * @return Mixed: Unescaped version of $data |
| 72 | + */ |
| 73 | + public static function unescape( $data ) { |
| 74 | + if ( is_array( $data ) ) { |
| 75 | + foreach ( array_keys( $data ) as $key ) { |
| 76 | + $data[$key] = self::unescape( $data[$key] ); |
| 77 | + } |
| 78 | + return $data; |
| 79 | + } |
| 80 | + return htmlspecialchars_decode( $data ); |
| 81 | + } |
| 82 | + |
| 83 | + /** |
50 | 84 | * Renders XML attributes from an array of key and value pairs. If a value is an array, it's |
51 | 85 | * imploded using a space as a delimiter. If any attributes are rendered, the result is preceded |
52 | | - * with a single space, otherwise the result is an empty string. |
| 86 | + * with a single space, otherwise the result is an empty string. Keys will be escaped (but |
| 87 | + * should have never had any escapable characters in them anyways) and values are assumed to be |
| 88 | + * escaped already (since data given to the template is escaped by default). |
| 89 | + * |
| 90 | + * @param $data Mixed: Data to unescape, either a string or array of strings |
| 91 | + * @return String: XML-style attributes |
53 | 92 | */ |
54 | | - public static function attributes( $attributes ) { |
| 93 | + public static function attributes( $data ) { |
55 | 94 | $result = array(); |
56 | | - if ( is_array( $attributes ) ) { |
57 | | - foreach ( $attributes as $key => $value ) { |
| 95 | + if ( is_array( $data ) ) { |
| 96 | + foreach ( $data as $key => $value ) { |
58 | 97 | if ( is_array( $value ) ) { |
59 | | - $result[] = $key . '="' . implode( ' ', self::escape( $value ) ) . '"'; |
| 98 | + // Named list of attributes |
| 99 | + $result[] = htmlspecialchars( $key ) . '="' . implode( ' ', $value ) . '"'; |
| 100 | + } else if ( is_string( $key ) ) { |
| 101 | + // Named attribute |
| 102 | + $result[] = htmlspecialchars( $key ) . '="' . $value . '"'; |
60 | 103 | } else { |
61 | | - $result[] = $key . '="' . self::escape( $value ) . '"'; |
| 104 | + // Value-less attribute such as "checked" |
| 105 | + $result[] = $value; |
62 | 106 | } |
63 | 107 | } |
| 108 | + } else { |
| 109 | + // Value-less attribute such as "checked" |
| 110 | + $result[] = $value; |
64 | 111 | } |
65 | 112 | return count( $result ) ? ( ' ' . implode( ' ', $result ) ) : ''; |
66 | 113 | } |
Index: trunk/extensions/HtmlUi/templates/HtmlUiFieldset.php |
— | — | @@ -1,4 +1,4 @@ |
2 | | -<fieldset class="htmlUiFieldset" rel="<?php echo self::escape( $id ) ?>"> |
| 2 | +<fieldset class="htmlUiFieldset" rel="<?php echo $id ?>"> |
3 | 3 | <?php foreach( $elements as $element ): ?> |
4 | 4 | <?php echo $element->render(); ?> |
5 | 5 | <?php endforeach; ?> |