/SafeUrl.class.php

https://github.com/timemachine3030/safe-url · PHP · 147 lines · 87 code · 4 blank · 56 comment · 6 complexity · e92f1197022d26fddf5286ef5527f5f3 MD5 · raw file

  1. <?php
  2. /**
  3. * This short class will turn user entered titles into URLs
  4. * that are keyword rich and human readable. For use with
  5. * Apache's mod rewrite.
  6. *
  7. * @author scottayy@gmail.com
  8. * @author Daniel Lopretto (http://daniellopretto.com)
  9. * @author Adrián Granado (https://github.com/playmono)
  10. *
  11. */
  12. class SafeUrl {
  13. /**
  14. * decode html entities in string?
  15. * @var boolean
  16. */
  17. static $decode = true;
  18. /**
  19. * charset to use if $decode is set to true
  20. * @var string
  21. */
  22. static $decode_charset = 'UTF-8';
  23. /**
  24. * turns string into all lowercase letters
  25. * @var boolean
  26. */
  27. static $lowercase = true;
  28. /**
  29. * strip out html tags from string?
  30. * @var boolean
  31. */
  32. static $strip = true;
  33. /**
  34. * maximum length of resulting title
  35. * @var int
  36. */
  37. static $maxlength = 50;
  38. /**
  39. * if maxlength is reached, chop at nearest whole word? or hard chop?
  40. * @var boolean
  41. */
  42. static $whole_word = true;
  43. /**
  44. * what title to use if no alphanumeric characters can be found
  45. * @var string
  46. */
  47. static $blank = 'no-title';
  48. /**
  49. * Allow a differnt character to be used as the separator.
  50. * @var string
  51. */
  52. static $separator = '-';
  53. /**
  54. * A table of UTF-8 characters and what to make them.
  55. * @link http://www.php.net/manual/en/function.strtr.php#90925
  56. * @var array
  57. */
  58. static $translation_table = array(
  59. 'Š'=>'S', 'š'=>'s', 'Đ'=>'Dj','Ð'=>'Dj','đ'=>'dj', 'Ž'=>'Z', 'ž'=>'z', 'Č'=>'C', 'č'=>'c', 'Ć'=>'C', 'ć'=>'c',
  60. 'À'=>'A', 'Á'=>'A', 'Â'=>'A', 'Ã'=>'A', 'Ä'=>'A', 'Å'=>'A', 'Æ'=>'A', 'Ç'=>'C', 'È'=>'E', 'É'=>'E',
  61. 'Ê'=>'E', 'Ë'=>'E', 'Ì'=>'I', 'Í'=>'I', 'Î'=>'I', 'Ï'=>'I', 'Ñ'=>'N', 'Ò'=>'O', 'Ó'=>'O', 'Ô'=>'O',
  62. 'Õ'=>'O', 'Ö'=>'O', 'Ø'=>'O', 'Ù'=>'U', 'Ú'=>'U', 'Û'=>'U', 'Ü'=>'U', 'Ý'=>'Y', 'Þ'=>'B', 'ß'=>'Ss',
  63. 'à'=>'a', 'á'=>'a', 'â'=>'a', 'ã'=>'a', 'ä'=>'a', 'å'=>'a', 'æ'=>'a', 'ç'=>'c', 'è'=>'e', 'é'=>'e',
  64. 'ê'=>'e', 'ë'=>'e', 'ì'=>'i', 'í'=>'i', 'î'=>'i', 'ï'=>'i', 'ð'=>'o', 'ñ'=>'n', 'ò'=>'o', 'ó'=>'o',
  65. 'ô'=>'o', 'õ'=>'o', 'ö'=>'o', 'ø'=>'o', 'ù'=>'u', 'ú'=>'u', 'û'=>'u', 'ý'=>'y', 'ý'=>'y', 'þ'=>'b',
  66. 'ÿ'=>'y', 'Ŕ'=>'R', 'ŕ'=>'r',
  67. /**
  68. * Special characters:
  69. */
  70. "'" => '', // Single quote
  71. '&' => ' and ', // Amperstand
  72. "\r\n" => ' ', // Newline
  73. "\n" => ' ' // Newline
  74. );
  75. /**
  76. * Helper method that uses the translation table to convert
  77. * non-ascii characters to a resonalbe alternative.
  78. *
  79. * @param string $text
  80. * @param array $options
  81. * @return string
  82. */
  83. static public function convertCharacters($text) {
  84. $text = html_entity_decode($text, ENT_QUOTES, static::$decode_charset);
  85. $text = strtr($text, static::$translation_table);
  86. return $text;
  87. }
  88. /**
  89. * the worker function
  90. *
  91. * @param string $text
  92. * @return string
  93. */
  94. static public function makeUrl($text, $options = null) {
  95. if (is_array($options)) {
  96. foreach($options as $property => $value) {
  97. static::$$property = $value;
  98. }
  99. }
  100. //Shortcut
  101. $s = static::$separator;
  102. //prepare the string according to our options
  103. if (static::$decode) {
  104. $text = static::convertCharacters($text);
  105. }
  106. if (static::$lowercase) {
  107. $text = strtolower($text);
  108. }
  109. if (static::$strip) {
  110. $text = strip_tags($text);
  111. }
  112. //filter
  113. $text = preg_replace("/[^&a-z0-9_-\s']/i", '', $text);
  114. $text = str_replace(' ', $s, $text);
  115. $text = trim(preg_replace("/{$s}{2,}/", $s, $text), $s);
  116. //chop?
  117. if (strlen($text) > static::$maxlength) {
  118. $text = substr($text, 0, static::$maxlength);
  119. if (static::$whole_word) {
  120. /**
  121. * If maxlength is small and leaves us with only part of one
  122. * word ignore the "whole_word" filtering.
  123. */
  124. $words = explode($s, $text);
  125. $temp = implode($s, array_diff($words, array(array_pop($words))));
  126. if ($temp != '') {
  127. $text = $temp;
  128. }
  129. }
  130. }
  131. //return =]
  132. if ($text == '') {
  133. return null;
  134. }
  135. return $text;
  136. }
  137. }