PageRenderTime 54ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/base/lib/flourishlib/fHTML.php

https://bitbucket.org/thanhtungnguyenphp/monitos
PHP | 318 lines | 140 code | 47 blank | 131 comment | 25 complexity | ca047ade885d058578b1a94a5e033202 MD5 | raw file
  1. <?php
  2. /**
  3. * Provides HTML-related methods
  4. *
  5. * This class is implemented to use the UTF-8 character encoding. Please see
  6. * http://flourishlib.com/docs/UTF-8 for more information.
  7. *
  8. * @copyright Copyright (c) 2007-2010 Will Bond
  9. * @author Will Bond [wb] <will@flourishlib.com>
  10. * @license http://flourishlib.com/license
  11. *
  12. * @package Flourish
  13. * @link http://flourishlib.com/fHTML
  14. *
  15. * @version 1.0.0b8
  16. * @changes 1.0.0b8 Changed ::encode() and ::prepare() to handle arrays of strings [wb, 2010-05-19]
  17. * @changes 1.0.0b7 Fixed a bug where some conditional comments were causing the regex in ::prepare() to break [wb, 2009-11-04]
  18. * @changes 1.0.0b6 Updated ::showChecked() to require strict equality if one parameter is `NULL` [wb, 2009-06-02]
  19. * @changes 1.0.0b5 Fixed ::prepare() so it does not encode multi-line HTML comments [wb, 2009-05-09]
  20. * @changes 1.0.0b4 Added methods ::printOption() and ::showChecked() that were in fCRUD [wb, 2009-05-08]
  21. * @changes 1.0.0b3 Fixed a bug where ::makeLinks() would double-link some URLs [wb, 2009-01-08]
  22. * @changes 1.0.0b2 Fixed a bug where ::makeLinks() would create links out of URLs in HTML tags [wb, 2008-12-05]
  23. * @changes 1.0.0b The initial implementation [wb, 2007-09-25]
  24. */
  25. class fHTML
  26. {
  27. // The following constants allow for nice looking callbacks to static methods
  28. const containsBlockLevelHTML = 'fHTML::containsBlockLevelHTML';
  29. const convertNewlines = 'fHTML::convertNewlines';
  30. const decode = 'fHTML::decode';
  31. const encode = 'fHTML::encode';
  32. const makeLinks = 'fHTML::makeLinks';
  33. const prepare = 'fHTML::prepare';
  34. const printOption = 'fHTML::printOption';
  35. const sendHeader = 'fHTML::sendHeader';
  36. const show = 'fHTML::show';
  37. const showChecked = 'fHTML::showChecked';
  38. /**
  39. * Checks a string of HTML for block level elements
  40. *
  41. * @param string $content The HTML content to check
  42. * @return boolean If the content contains a block level tag
  43. */
  44. static public function containsBlockLevelHTML($content)
  45. {
  46. static $inline_tags = '<a><abbr><acronym><b><big><br><button><cite><code><del><dfn><em><font><i><img><input><ins><kbd><label><q><s><samp><select><small><span><strike><strong><sub><sup><textarea><tt><u><var>';
  47. return strip_tags($content, $inline_tags) != $content;
  48. }
  49. /**
  50. * Converts newlines into `br` tags as long as there aren't any block-level HTML tags present
  51. *
  52. * @param string $content The content to display
  53. * @return void
  54. */
  55. static public function convertNewlines($content)
  56. {
  57. static $inline_tags_minus_br = '<a><abbr><acronym><b><big><button><cite><code><del><dfn><em><font><i><img><input><ins><kbd><label><q><s><samp><select><small><span><strike><strong><sub><sup><textarea><tt><u><var>';
  58. return (strip_tags($content, $inline_tags_minus_br) != $content) ? $content : nl2br($content);
  59. }
  60. /**
  61. * Converts all HTML entities to normal characters, using UTF-8
  62. *
  63. * @param string $content The content to decode
  64. * @return string The decoded content
  65. */
  66. static public function decode($content)
  67. {
  68. return html_entity_decode($content, ENT_QUOTES, 'UTF-8');
  69. }
  70. /**
  71. * Converts all special characters to entites, using UTF-8.
  72. *
  73. * @param string|array $content The content to encode
  74. * @return string The encoded content
  75. */
  76. static public function encode($content)
  77. {
  78. if (is_array($content)) {
  79. return array_map(array('fHTML', 'encode'), $content);
  80. }
  81. return htmlentities($content, ENT_QUOTES, 'UTF-8');
  82. }
  83. /**
  84. * Takes a block of text and converts all URLs into HTML links
  85. *
  86. * @param string $content The content to parse for links
  87. * @param integer $link_text_length If non-zero, all link text will be truncated to this many characters
  88. * @return string The content with all URLs converted to HTML link
  89. */
  90. static public function makeLinks($content, $link_text_length=0)
  91. {
  92. // Find all a tags with contents, individual HTML tags and HTML comments
  93. $reg_exp = "/<\s*a(?:\s+[\w:]+(?:\s*=\s*(?:\"[^\"]*?\"|'[^']*?'|[^'\">\s]+))?)*\s*>.*?<\s*\/\s*a\s*>|<\s*\/?\s*[\w:]+(?:\s+[\w:]+(?:\s*=\s*(?:\"[^\"]*?\"|'[^']*?'|[^'\">\s]+))?)*\s*\/?\s*>|<\!--.*?-->/s";
  94. preg_match_all($reg_exp, $content, $html_matches, PREG_SET_ORDER);
  95. // Find all text
  96. $text_matches = preg_split($reg_exp, $content);
  97. // For each chunk of text and create the links
  98. foreach($text_matches as $key => $text) {
  99. preg_match_all(
  100. '~
  101. \b([a-z]{3,}://[a-z0-9%\$\-_.+!*;/?:@=&\'\#,]+[a-z0-9\$\-_+!*;/?:@=&\'\#,])\b | # Fully URLs
  102. \b(www\.(?:[a-z0-9\-]+\.)+[a-z]{2,}(?:/[a-z0-9%\$\-_.+!*;/?:@=&\'\#,]+[a-z0-9\$\-_+!*;/?:@=&\'\#,])?)\b | # www. domains
  103. \b([a-z0-9\\.+\'_\\-]+@(?:[a-z0-9\\-]+\.)+[a-z]{2,})\b # email addresses
  104. ~ix',
  105. $text,
  106. $matches,
  107. PREG_SET_ORDER
  108. );
  109. // For each match we find the first occurence, replace it and then
  110. // start from the end of that finding the next occurence. This
  111. // prevents double linking of matches for http://www.example.com and
  112. // www.example.com
  113. $last_pos = 0;
  114. foreach ($matches as $match) {
  115. $match_pos = strpos($text, $match[0], $last_pos);
  116. $length = strlen($match[0]);
  117. $prefix = '';
  118. if (!empty($match[3])) {
  119. $prefix = 'mailto:';
  120. } elseif (!empty($match[2])) {
  121. $prefix = 'http://';
  122. }
  123. $replacement = '<a href="' . $prefix . $match[0] . '">';
  124. $replacement .= ($link_text_length && strlen($match[0]) > $link_text_length) ? substr($match[0], 0, $link_text_length) . "…" : $match[0];
  125. $replacement .= '</a>';
  126. $text = substr_replace(
  127. $text,
  128. $replacement,
  129. $match_pos,
  130. $length
  131. );
  132. $last_pos = $match_pos + strlen($replacement);
  133. }
  134. $text_matches[$key] = $text;
  135. }
  136. // Merge the text and html back together
  137. for ($i = 0; $i < sizeof($html_matches); $i++) {
  138. $text_matches[$i] .= $html_matches[$i][0];
  139. }
  140. return implode($text_matches);
  141. }
  142. /**
  143. * Prepares content for display in UTF-8 encoded HTML - allows HTML tags
  144. *
  145. * @param string|array $content The content to prepare
  146. * @return string The encoded html
  147. */
  148. static public function prepare($content)
  149. {
  150. if (is_array($content)) {
  151. return array_map(array('fHTML', 'prepare'), $content);
  152. }
  153. // Find all html tags, entities and comments
  154. $reg_exp = "/<\s*\/?\s*[\w:]+(?:\s+[\w:]+(?:\s*=\s*(?:\"[^\"]*?\"|'[^']*?'|[^'\">\s]+))?)*\s*\/?\s*>|&(?:#\d+|\w+);|<\!--.*?-->/s";
  155. preg_match_all($reg_exp, $content, $html_matches, PREG_SET_ORDER);
  156. // Find all text
  157. $text_matches = preg_split($reg_exp, $content);
  158. // For each chunk of text, make sure it is converted to entities
  159. foreach($text_matches as $key => $value) {
  160. $text_matches[$key] = htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
  161. }
  162. // Merge the text and html back together
  163. for ($i = 0; $i < sizeof($html_matches); $i++) {
  164. $text_matches[$i] .= $html_matches[$i][0];
  165. }
  166. return implode($text_matches);
  167. }
  168. /**
  169. * Prints an `option` tag with the provided value, using the selected value to determine if the option should be marked as selected
  170. *
  171. * @param string $text The text to display in the option tag
  172. * @param string $value The value for the option
  173. * @param string $selected_value If the value is the same as this, the option will be marked as selected
  174. * @return void
  175. */
  176. static public function printOption($text, $value, $selected_value=NULL)
  177. {
  178. $selected = FALSE;
  179. if ($value == $selected_value || (is_array($selected_value) && in_array($value, $selected_value))) {
  180. $selected = TRUE;
  181. }
  182. echo '<option value="' . fHTML::encode($value) . '"';
  183. if ($selected) {
  184. echo ' selected="selected"';
  185. }
  186. echo '>' . fHTML::prepare($text) . '</option>';
  187. }
  188. /**
  189. * Sets the proper Content-Type header for a UTF-8 HTML (or pseudo-XHTML) page
  190. *
  191. * @return void
  192. */
  193. static public function sendHeader()
  194. {
  195. header('Content-Type: text/html; charset=utf-8');
  196. }
  197. /**
  198. * Prints a `p` (or `div` if the content has block-level HTML) tag with the contents and the class specified - will not print if no content
  199. *
  200. * @param string $content The content to display
  201. * @param string $css_class The CSS class to apply
  202. * @return boolean If the content was shown
  203. */
  204. static public function show($content, $css_class='')
  205. {
  206. if ((!is_string($content) && !is_object($content) && !is_numeric($content)) || !strlen(trim($content))) {
  207. return FALSE;
  208. }
  209. $class = ($css_class) ? ' class="' . $css_class . '"' : '';
  210. if (self::containsBlockLevelHTML($content)) {
  211. echo '<div' . $class . '>' . self::prepare($content) . '</div>';
  212. } else {
  213. echo '<p' . $class . '>' . self::prepare($content) . '</p>';
  214. }
  215. return TRUE;
  216. }
  217. /**
  218. * Prints a `checked="checked"` HTML input attribute if `$value` equals `$checked_value`, or if `$value` is in `$checked_value`
  219. *
  220. * Please note that if either `$value` or `$checked_value` is `NULL`, a
  221. * strict comparison will be performed, whereas normally a non-strict
  222. * comparison is made. Thus `0` and `FALSE` will cause the checked
  223. * attribute to be printed, but `0` and `NULL` will not.
  224. *
  225. * @param string $value The value for the current HTML input tag
  226. * @param string|array $checked_value The value (or array of values) that has been checked
  227. * @return boolean If the checked attribute was printed
  228. */
  229. static public function showChecked($value, $checked_value)
  230. {
  231. $checked = FALSE;
  232. $one_null = $value === NULL || $checked_value === NULL;
  233. $equal = ($one_null) ? $value === $checked_value : $value == $checked_value;
  234. $in_array = is_array($checked_value) && in_array($value, $checked_value, $one_null ? TRUE : FALSE);
  235. if ($equal || $in_array) {
  236. $checked = TRUE;
  237. }
  238. if ($checked) {
  239. echo ' checked="checked"';
  240. return TRUE;
  241. }
  242. return FALSE;
  243. }
  244. /**
  245. * Forces use as a static class
  246. *
  247. * @return fHTML
  248. */
  249. private function __construct() { }
  250. }
  251. /**
  252. * Copyright (c) 2007-2010 Will Bond <will@flourishlib.com>
  253. *
  254. * Permission is hereby granted, free of charge, to any person obtaining a copy
  255. * of this software and associated documentation files (the "Software"), to deal
  256. * in the Software without restriction, including without limitation the rights
  257. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  258. * copies of the Software, and to permit persons to whom the Software is
  259. * furnished to do so, subject to the following conditions:
  260. *
  261. * The above copyright notice and this permission notice shall be included in
  262. * all copies or substantial portions of the Software.
  263. *
  264. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  265. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  266. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  267. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  268. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  269. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  270. * THE SOFTWARE.
  271. */