[Fusionforge-commits] r15447 - in branches/Branch_5_1/src: common/include docs www/include
Thorsten Glaser
mirabilos at fusionforge.org
Wed May 2 09:52:02 CEST 2012
Author: mirabilos
Date: 2012-05-02 09:52:00 +0200 (Wed, 02 May 2012)
New Revision: 15447
Added:
branches/Branch_5_1/src/docs/README.html:elements
branches/Branch_5_1/src/docs/README.html:utils
Modified:
branches/Branch_5_1/src/common/include/utils.php
branches/Branch_5_1/src/www/include/html.php
Log:
port a few utility functions from Evolvis (and their documentation)
to make it easier to port over fixes from it
Modified: branches/Branch_5_1/src/common/include/utils.php
===================================================================
--- branches/Branch_5_1/src/common/include/utils.php 2012-04-29 17:30:31 UTC (rev 15446)
+++ branches/Branch_5_1/src/common/include/utils.php 2012-05-02 07:52:00 UTC (rev 15447)
@@ -5,7 +5,7 @@
* Copyright 1999-2001, VA Linux Systems, Inc.
* Copyright 2009-2010, Roland Mas
* Copyright 2009-2010, Franck Villaume - Capgemini
- * Copyright (c) 2010, 2011
+ * Copyright (c) 2010, 2011, 2012
* Thorsten Glaser <t.glaser at tarent.de>
* Copyright (C) 2010-2011 Alain Peyrat - Alcatel-Lucent
*
@@ -368,15 +368,7 @@
*
*/
function util_unconvert_htmlspecialchars($string) {
- if (strlen($string) < 1) {
- return '';
- } else {
- //$trans = get_html_translation_table(HTMLENTITIES, ENT_QUOTES);
- $trans = get_html_translation_table(HTML_ENTITIES);
- $trans = array_flip ($trans);
- $str = strtr ($string, $trans);
- return $str;
- }
+ return html_entity_decode($string, ENT_QUOTES, "UTF-8");
}
/**
@@ -1476,12 +1468,47 @@
return $s;
}
+function util_html_encode($s) {
+ return htmlspecialchars($s, ENT_QUOTES, "UTF-8");
+}
+
/* secure a (possibly already HTML encoded) string */
function util_html_secure($s) {
- return htmlentities(html_entity_decode($s, ENT_QUOTES, "UTF-8"),
- ENT_QUOTES, "UTF-8");
+ return util_html_encode(util_unconvert_htmlspecialchars($s));
}
+/* return integral value (ℕ₀) of passed string if it matches, or false */
+function util_nat0(&$s) {
+ if (!isset($s)) {
+ /* unset variable */
+ return false;
+ }
+ if (is_array($s)) {
+ if (count($s) == 1) {
+ /* one-element array */
+ return util_nat0($s[0]);
+ }
+ /* not one element, or element not at [0] */
+ return false;
+ }
+ if (!is_numeric($s)) {
+ /* not numeric */
+ return false;
+ }
+ $num = (int)$s;
+ if ($num >= 0) {
+ /* number element of ℕ₀ */
+ $text = (string)$num;
+ if ($text == $s) {
+ /* number matches its textual representation */
+ return ($num);
+ }
+ /* doesn't match, like 0123 or 1.2 or " 1" */
+ }
+ /* or negative */
+ return false;
+}
+
/**
* Codendi compatibility code.
*
@@ -1491,9 +1518,39 @@
return forge_check_global_perm('forge_admin');
}
+/**
+ * util_gethref() - Construct a hypertext reference
+ *
+ * @param string $baseurl
+ * (optional) base URL (absolute or relative);
+ * urlencoded, but not htmlencoded
+ * (default (falsy): PHP_SELF)
+ * @param array $args
+ * (optional) associative array of unencoded query parameters;
+ * false values are ignored
+ * @param bool $ashtml
+ * (optional) htmlencode the result?
+ * (default: true)
+ * @param string $sep
+ * (optional) argument separator ('&' or ';')
+ * (default: '&')
+ * @return string
+ * URL, possibly htmlencoded
+ */
+function util_gethref($baseurl=false, $args=array(), $ashtml=true, $sep='&') {
+ $rv = $baseurl ? $baseurl : getStringFromServer('PHP_SELF');
+ $pfx = '?';
+ foreach ($args as $k => $v) {
+ if ($v === false) {
+ continue;
+ }
+ $rv .= $pfx . urlencode($k) . '=' . urlencode($v);
+ $pfx = $sep;
+ }
+ return ($ashtml ? util_html_encode($rv) : $rv);
+}
+
// Local Variables:
// mode: php
// c-file-style: "bsd"
// End:
-
-?>
Added: branches/Branch_5_1/src/docs/README.html:elements
===================================================================
--- branches/Branch_5_1/src/docs/README.html:elements (rev 0)
+++ branches/Branch_5_1/src/docs/README.html:elements 2012-05-02 07:52:00 UTC (rev 15447)
@@ -0,0 +1,142 @@
+Documentation of new HTML element creation functions
+────────────────────────────────────────────────────
+
+Functions defined in src/www/include/html.php → available: always.
+
+
+‣ Element emission functions (do not echo anything)
+
+
+• string html_eo(string $name, optional(empty) array $attrs)
+
+ html_eo('b')
+ ⇒ '<b>'
+
+ html_eo('td', array('colspan' => 2))
+ ⇒ '<td colspan="2">'
+
+ html_eo('div', array('class' => array('ff', 'important')))
+ ⇒ '<div class="ff important">'
+
+ html_eo('img', array(
+ 'src' => '…',
+ 'ref' => false,
+ 'class' => array(),
+ 'alt' => "",
+ ))
+ ⇒ '<img src="…" alt="">'
+
+ Generate an XHTML E̲lement O̲pen tag for $name, with attributes
+ defined by key/value pairs properly inserted. Attribute values
+ are coerced into strings from integers (by casting) or arrays
+ (by concatenating the array elements with spaces); if the value
+ is === false or an empty array (count($attrs[n]) == 0), the
+ attribute is not output at all, but for empty values it is; see
+ the img example (admittedly bad, you’d use html_e() for "img").
+
+• string html_e(string $name, optional(empty) array $attrs,
+ optional(empty) string $content, optional(true) bool $shortform)
+
+ html_e('br')
+ ⇒ '<br />'
+
+ html_e('a', array('href' => '/foo.php?a=1&b=2'), 'täxt')
+ ⇒ '<a href="/foo.php?a=1&b=2">täxt</a>'
+
+ html_e('script', array(
+ 'type' => 'text/javascript',
+ 'src' => '/js/foo.js',
+ ), "", false)
+ ⇒ '<script type="text/javascript" src="/js/foo.js"></script>'
+ /* needed because <script ... /> does not work */
+
+ html_e('tr', array(), html_e('td', array(), 'bla'))
+ ⇒ '<tr><td>bla</td></tr>'
+
+ As with html_eo() the first two arguments define the tag to open.
+ The third argument will be placed between the opening and closing
+ tags but – in contrast to attribute values – not entity-encoded.
+ If the third argument is empty, either a self-closing (default)
+ tag, or, if the fourth argument is false, an open-close sequence,
+ is emitted.
+
+
+‣ Autoclose stack functions
+
+ $spos = html_ap();
+ $s = html_ao('p');
+ if ($foo) {
+ $s .= html_ao('strong');
+ }
+ $s .= html_ao('a', array('href' => '/'));
+ $s .= somefunc();
+ $s .= html_ac($spos);
+ ⇒ '<p><strong><a href="/">somefuncreturnvalue</a></strong></p>'
+ ⇒ '<p><a href="/">somefuncreturnvalue</a></p>'
+
+• integer html_ap(void)
+
+ Return the a̲utoclose stack’s current p̲osition.
+
+• string html_ao(string $name, optional(empty) array $attrs)
+
+ Works the same as html_eo() but pushes $name onto the a̲utoclose
+ element stack when o̲pening it.
+
+• string html_ac(integer $spos)
+
+ Return a set of closing elements until the a̲utoc̲lose stack
+ has reached the position it had when html_ap() returned $spos.
+
+ If $spos === false: an empty string is returned, for html_aonce().
+
+ If $spos < current stack position, an Exception is raised.
+
+• string html_aonce(ByRef integer $sptr, string $name,
+ optional(empty) array $attrs)
+
+ $spos = false;
+ foreach ($row in $rows) {
+ echo html_aonce('table');
+ echo html_e('tr', array(), html_e('td', array(),
+ util_html_secure($row['data'])));
+ }
+ echo html_ac($spos);
+ ⇒ '' // if $rows is empty
+ ⇒ '<table><tr><td>content1</td></tr><tr><td>content2</td></tr></table>'
+
+ If $sptr is not false, do nothing. Otherwise, set it to
+ the current html_ap() then do html_ao($name, $attrs).
+
+ This function can easily be used to open an enclosing element
+ with mandatory inner elements, such as a table, only once except
+ if no table row were to be generated.
+
+‣ Autoclose stack copy functions
+
+ $spos = html_ap();
+ echo html_ao('tr', array('bgcolor' => '#FF0000'));
+ echo html_ao('td');
+ echo "content 1";
+ $scopy = html_a_copy($spos);
+ echo html_ac($spos);
+ echo html_e('tr', array(), html_e('td', array(), "intermediate"));
+ echo html_a_apply($scopy);
+ echo "content 2";
+ echo html_ac($spos);
+ echo html_a_apply($scopy);
+ echo "content 3";
+ echo html_ac($spos);
+
+ ⇒ <tr bgcolor="#FF0000"><td>content 1</td></tr>
+ <tr><td>intermediate</td></tr>
+ <tr bgcolor="#FF0000"><td>content 2</td></tr>
+ <tr bgcolor="#FF0000"><td>content 3</td></tr>
+
+• opaque html_a_copy(integer $spos)
+• string html_a_apply(opaque $scopy)
+
+ Before autoclosing the stack down to a level $spos, you can
+ retrieve a copy of the stack in an opaque format, which can
+ later be used to (re-)open the same elements, with the same
+ attributes, even in a different nesting state.
Added: branches/Branch_5_1/src/docs/README.html:utils
===================================================================
--- branches/Branch_5_1/src/docs/README.html:utils (rev 0)
+++ branches/Branch_5_1/src/docs/README.html:utils 2012-05-02 07:52:00 UTC (rev 15447)
@@ -0,0 +1,102 @@
+Documentation of common HTML utility functions
+──────────────────────────────────────────────
+
+Functions defined in src/common/include/utils.php → available: always.
+
+
+• string util_html_encode(string $s)
+
+ util_html_secure('a=1&b=2')
+ ⇒ 'a=1&b=2' // HTML-encoded
+
+ util_html_secure('a=1&b=2')
+ ⇒ 'a=1&b=2' // changed!
+
+ Encode a string for use in XHTML even if it is already encoded.
+
+• string util_html_secure(string $s)
+
+ util_html_secure('a=1&b=2')
+ ⇒ 'a=1&b=2' // HTML-encoded
+
+ util_html_secure('a=1&b=2')
+ ⇒ 'a=1&b=2' // unchanged
+
+ Encode a string for use in XHTML if it is not already encoded.
+ (So, if you use this for output sanitising, other than a slight
+ performance penalty no harm is done if the output was already
+ sane.)
+
+• string util_unconvert_htmlspecialchars(string $s)
+
+ util_unconvert_htmlspecialchars('a=1&b=2')
+ ⇒ 'a=1&b=2' // unchanged
+
+ util_unconvert_htmlspecialchars('a=1&b=2')
+ ⇒ 'a=1&b=2' // HTML-decoded
+
+ Undo util_html_encode; be careful, this can decode partially.
+
+
+• string util_gethref(optional(false) string $baseurl,
+ optional(empty) array $args, optional(true) bool $ashtml,
+ optional('&') string $sep)
+
+ util_gethref("/x.php", array(
+ 'foo' => 'a+b&c',
+ 'bar' => 'd+b&e',
+ ));
+ ⇒ "/x.php?foo=a%2Bb%26c&bar=d%2Bb%26e"
+
+ util_gethref("/x.php", array(
+ 'foo' => 'a+b&c',
+ 'bar' => 'd+b&e',
+ ), false);
+ ⇒ /x.php?foo=a%2Bb%26c&bar=d%2Bb%26e
+
+ util_gethref("/x.php", array(
+ 'foo' => 'a+b&c',
+ 'bar' => 'd+b&e',
+ ), true, ';')
+ ⇒ "/x.php?foo=a%2Bb%26c;bar=d%2Bb%26e"
+
+ Construct an URI for use with util_make_url, session_redirect,
+ html_e('a', array('href' => …)), and similar. The first argument
+ ($baseurl) is passed through as-is but, if falsy, defaults to
+ getStringFromServer('PHP_SELF'); the arguments (both keys and
+ values) are urlencoded (entries while values is false are not
+ emitted at all) and appended, with a question mark in front and
+ the $sep separator in between.
+
+ If $ashtml is true (default), the result will then be run through
+ util_html_encode; set this to false when using in html_e href as
+ value (since html_e will html-encode itself).
+
+• string util_make_url(string $path)
+
+ util_make_url('/foo.php?a=1&b=2')
+ ⇒ 'https://forge.domain.com/fusionforge/foo.php?a=1&b=2'
+
+ Return an absolute URI for the path in question, containing the
+ system-defined protocol, hostname and (if defined) webroot prefix.
+
+ Both html-encoded and not html-encoded return values of util_gethref
+ are safe to pass as arguments, if their baseurl was only a path.
+
+• integer|false util_nat0(ByRef string $s)
+
+ If and only if $s is the normalised positive integer (ℕ₀)
+ representation of a number, return that number; false otherwise.
+ Limited by system constraints, i.e. usually [0;2³¹-1].
+
+
+‣ common non-HTML utility functions
+
+
+• mixed util_ifsetor(ByRef mixed $val, optional(false) mixed $default)
+
+ If isset($val), return $val, otherwise (no warning) $default.
+
+• string debug_string_backtrace(void)
+
+ Return the current debugging backtrace as string.
Modified: branches/Branch_5_1/src/www/include/html.php
===================================================================
--- branches/Branch_5_1/src/www/include/html.php 2012-04-29 17:30:31 UTC (rev 15446)
+++ branches/Branch_5_1/src/www/include/html.php 2012-05-02 07:52:00 UTC (rev 15447)
@@ -850,9 +850,210 @@
return $hashstr;
}
+/* TODO: think about beautifying output */
+
+/**
+ * html_eo() - Return proper element XHTML start tag
+ *
+ * @param string $name
+ * element name
+ * @param array $attrs
+ * (optional) associative array of element attributes
+ * values: arrays are space-imploded;
+ * false values and empty arrays ignored
+ * @return string
+ * XHTML string suitable for echo'ing
+ */
+function html_eo($name, $attrs=array()) {
+ $rv = '<' . $name;
+ foreach ($attrs as $key => $value) {
+ if (is_array($value)) {
+ $value = count($value) ? implode(" ", $value) : false;
+ }
+ if ($value === false) {
+ continue;
+ }
+ $rv .= ' ' . $key . '="' . htmlspecialchars($value) . '"';
+ }
+ $rv .= '>';
+ return $rv;
+}
+
+/**
+ * html_e() - Return proper element XHTML start/end sequence
+ *
+ * @param string $name
+ * element name
+ * @param array $attrs
+ * (optional) associative array of element attributes
+ * values: arrays are space-imploded;
+ * false values and empty arrays ignored
+ * @param string $content
+ * (optional) XHTML to be placed inside
+ * @param bool $shortform
+ * (optional) allow short open-close form
+ * (default: true)
+ * @return string
+ * XHTML string suitable for echo'ing
+ */
+function html_e($name, $attrs=array(), $content="", $shortform=true) {
+ $rv = '<' . $name;
+ foreach ($attrs as $key => $value) {
+ if (is_array($value)) {
+ $value = count($value) ? implode(" ", $value) : false;
+ }
+ if ($value === false) {
+ continue;
+ }
+ $rv .= ' ' . $key . '="' . htmlspecialchars($value) . '"';
+ }
+ if ($content === "" && $shortform) {
+ $rv .= ' />';
+ } else {
+ $rv .= '>' . $content . '</' . $name . '>';
+ }
+ return $rv;
+}
+
+$html_autoclose_stack = array();
+$html_autoclose_pos = 0;
+
+/**
+ * html_ap() - Return XHTML element autoclose stack position
+ *
+ * @return integer
+ */
+function html_ap() {
+ global $html_autoclose_pos;
+
+ return $html_autoclose_pos;
+}
+
+/**
+ * html_ao() - Return proper element XHTML start tag, with autoclose
+ *
+ * @param string $name
+ * element name
+ * @param array $attrs
+ * (optional) associative array of element attributes
+ * values: arrays are space-imploded;
+ * false values and empty arrays ignored
+ * @return string
+ * XHTML string suitable for echo'ing
+ */
+function html_ao($name, $attrs=array()) {
+ global $html_autoclose_pos, $html_autoclose_stack;
+
+ $html_autoclose_stack[$html_autoclose_pos++] = array(
+ 'name' => $name,
+ 'attr' => $attrs,
+ );
+ return html_eo($name, $attrs);
+}
+
+/**
+ * html_aonce() - Return once proper element XHTML start tag, with autoclose
+ *
+ * @param ref &$sptr
+ initialise this to false; will be modified
+ * @param string $name
+ * element name
+ * @param array $attrs
+ * (optional) associative array of element attributes
+ * values: arrays are space-imploded;
+ * false values and empty arrays ignored
+ * @return string
+ * XHTML string suitable for echo'ing
+ */
+function html_aonce(&$sptr, $name, $attrs=array()) {
+ if ($sptr !== false) {
+ /* already run */
+ return "";
+ }
+ $sptr = html_ap();
+ return html_ao($name, $attrs);
+}
+
+/**
+ * html_ac() - Return proper element XHTML end tags, autoclosing
+ *
+ * @param integer $spos
+ * stack position to return to
+ * (nothing is done if === false)
+ * @return string
+ * XHTML string suitable for echo'ing
+ */
+function html_ac($spos) {
+ global $html_autoclose_pos, $html_autoclose_stack;
+
+ if ($spos === false) {
+ /* support for html_aonce() */
+ return "";
+ }
+
+ if ($html_autoclose_pos < $spos) {
+ $e = "html_autoclose stack underflow; closing down to " .
+ $spos . " but we're down to " . $html_autoclose_pos .
+ " already!";
+ throw new Exception($e);
+ }
+
+ $rv = "";
+ while ($html_autoclose_pos > $spos) {
+ --$html_autoclose_pos;
+ $rv .= '</' . $html_autoclose_stack[$html_autoclose_pos]['name'] . '>';
+ unset($html_autoclose_stack[$html_autoclose_pos]);
+ }
+ return $rv;
+}
+
+/**
+ * html_a_copy() - Return a copy of part of the autoclose stack
+ *
+ * @param integer $spos
+ * stack position caller will return to
+ * @return opaque
+ * argument suitable for html_a_apply()
+ */
+function html_a_copy($spos) {
+ global $html_autoclose_pos, $html_autoclose_stack;
+
+ if ($spos === false) {
+ return array();
+ }
+
+ if ($spos > $html_autoclose_pos) {
+ $e = "html_autoclose stack underflow; closing down to " .
+ $spos . " but we're down to " . $html_autoclose_pos .
+ " already!";
+ throw new Exception($e);
+ }
+
+ $rv = array();
+ while ($spos < $html_autoclose_pos) {
+ $rv[] = $html_autoclose_stack[$spos++];
+ }
+ return $rv;
+}
+
+/**
+ * html_a_apply() - Reopen tags based on an autoclose stack copy
+ *
+ * @param opaque $scopy
+ * return value from html_a_copy()
+ * @return string
+ * XHTML string suitable for echo'ing
+ */
+function html_a_apply($scopy) {
+ /* array_reduce() would be useful here... IF IT WORKED, FFS! */
+ $rv = "";
+ foreach ($scopy as $value) {
+ $rv .= html_ao($value['name'], $value['attr']);
+ }
+ return $rv;
+}
+
// Local Variables:
// mode: php
// c-file-style: "bsd"
// End:
-
-?>
More information about the Fusionforge-commits
mailing list