PageRenderTime 40ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/filter/urltolink/filter.php

https://bitbucket.org/kudutest1/moodlegit
PHP | 169 lines | 63 code | 19 blank | 87 comment | 12 complexity | 64e4ba9fed435383d25259aab2df8880 MD5 | raw file
  1. <?php
  2. // This file is part of Moodle - http://moodle.org/
  3. //
  4. // Moodle is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // Moodle is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License
  15. // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
  16. /**
  17. * Filter converting URLs in the text to HTML links
  18. *
  19. * @package filter
  20. * @subpackage urltolink
  21. * @copyright 2010 David Mudrak <david@moodle.com>
  22. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23. */
  24. defined('MOODLE_INTERNAL') || die();
  25. class filter_urltolink extends moodle_text_filter {
  26. /**
  27. * @var array global configuration for this filter
  28. *
  29. * This might be eventually moved into parent class if we found it
  30. * useful for other filters, too.
  31. */
  32. protected static $globalconfig;
  33. /**
  34. * Apply the filter to the text
  35. *
  36. * @see filter_manager::apply_filter_chain()
  37. * @param string $text to be processed by the text
  38. * @param array $options filter options
  39. * @return string text after processing
  40. */
  41. public function filter($text, array $options = array()) {
  42. if (!isset($options['originalformat'])) {
  43. // if the format is not specified, we are probably called by {@see format_string()}
  44. // in that case, it would be dangerous to replace URL with the link because it could
  45. // be stripped. therefore, we do nothing
  46. return $text;
  47. }
  48. if (in_array($options['originalformat'], explode(',', $this->get_global_config('formats')))) {
  49. $this->convert_urls_into_links($text);
  50. }
  51. return $text;
  52. }
  53. ////////////////////////////////////////////////////////////////////////////
  54. // internal implementation starts here
  55. ////////////////////////////////////////////////////////////////////////////
  56. /**
  57. * Returns the global filter setting
  58. *
  59. * If the $name is provided, returns single value. Otherwise returns all
  60. * global settings in object. Returns null if the named setting is not
  61. * found.
  62. *
  63. * @param mixed $name optional config variable name, defaults to null for all
  64. * @return string|object|null
  65. */
  66. protected function get_global_config($name=null) {
  67. $this->load_global_config();
  68. if (is_null($name)) {
  69. return self::$globalconfig;
  70. } elseif (array_key_exists($name, self::$globalconfig)) {
  71. return self::$globalconfig->{$name};
  72. } else {
  73. return null;
  74. }
  75. }
  76. /**
  77. * Makes sure that the global config is loaded in $this->globalconfig
  78. *
  79. * @return void
  80. */
  81. protected function load_global_config() {
  82. if (is_null(self::$globalconfig)) {
  83. self::$globalconfig = get_config('filter_urltolink');
  84. }
  85. }
  86. /**
  87. * Given some text this function converts any URLs it finds into HTML links
  88. *
  89. * @param string $text Passed in by reference. The string to be searched for urls.
  90. */
  91. protected function convert_urls_into_links(&$text) {
  92. //I've added img tags to this list of tags to ignore.
  93. //See MDL-21168 for more info. A better way to ignore tags whether or not
  94. //they are escaped partially or completely would be desirable. For example:
  95. //<a href="blah">
  96. //&lt;a href="blah"&gt;
  97. //&lt;a href="blah">
  98. $filterignoretagsopen = array('<a\s[^>]+?>');
  99. $filterignoretagsclose = array('</a>');
  100. filter_save_ignore_tags($text,$filterignoretagsopen,$filterignoretagsclose,$ignoretags);
  101. // Check if we support unicode modifiers in regular expressions. Cache it.
  102. // TODO: this check should be a environment requirement in Moodle 2.0, as far as unicode
  103. // chars are going to arrive to URLs officially really soon (2010?)
  104. // Original RFC regex from: http://www.bytemycode.com/snippets/snippet/796/
  105. // Various ideas from: http://alanstorm.com/url_regex_explained
  106. // Unicode check, negative assertion and other bits from Moodle.
  107. static $unicoderegexp;
  108. if (!isset($unicoderegexp)) {
  109. $unicoderegexp = @preg_match('/\pL/u', 'a'); // This will fail silently, returning false,
  110. }
  111. //todo: MDL-21296 - use of unicode modifiers may cause a timeout
  112. if ($unicoderegexp) { //We can use unicode modifiers
  113. $text = preg_replace('#(?<!=["\'])(((http(s?))://)(((([\pLl0-9]([\pLl0-9]|-)*[\pLl0-9]|[\pLl0-9])\.)+([\pLl]([\pLl0-9]|-)*[\pLl0-9]|[\pLl]))|(([0-9]{1,3}\.){3}[0-9]{1,3}))(:[\pL0-9]*)?(/([\pLl0-9\.!$&\'\(\)*+,;=_~:@-]|%[a-fA-F0-9]{2})*)*(\?([\pLl0-9\.!$&\'\(\)*+,;=_~:@/?-]|%[a-fA-F0-9]{2})*)?(\#[\pLl0-9\.!$&\'\(\)*+,;=_~:@/?-]*)?)(?<![,.;])#iu',
  114. '<a href="\\1" class="_blanktarget">\\1</a>', $text);
  115. $text = preg_replace('#(?<!=["\']|//)((www\.([\pLl0-9]([\pLl0-9]|-)*[\pLl0-9]|[\pLl0-9])\.)+([\pLl]([\pLl0-9]|-)*[\pLl0-9]|[\pLl])(:[\pL0-9]*)?(/([\pLl0-9\.!$&\'\(\)*+,;=_~:@-]|%[a-fA-F0-9]{2})*)*(\?([\pLl0-9\.!$&\'\(\)*+,;=_~:@/?-]|%[a-fA-F0-9]{2})*)?(\#[\pLl0-9\.!$&\'\(\)*+,;=_~:@/?-]*)?)(?<![,.;])#iu',
  116. '<a href="http://\\1" class="_blanktarget">\\1</a>', $text);
  117. } else { //We cannot use unicode modifiers
  118. $text = preg_replace('#(?<!=["\'])(((http(s?))://)(((([a-z0-9]([a-z0-9]|-)*[a-z0-9]|[a-z0-9])\.)+([a-z]([a-z0-9]|-)*[a-z0-9]|[a-z]))|(([0-9]{1,3}\.){3}[0-9]{1,3}))(:[a-zA-Z0-9]*)?(/([a-z0-9\.!$&\'\(\)*+,;=_~:@-]|%[a-f0-9]{2})*)*(\?([a-z0-9\.!$&\'\(\)*+,;=_~:@/?-]|%[a-fA-F0-9]{2})*)?(\#[a-z0-9\.!$&\'\(\)*+,;=_~:@/?-]*)?)(?<![,.;])#i',
  119. '<a href="\\1" class="_blanktarget">\\1</a>', $text);
  120. $text = preg_replace('#(?<!=["\']|//)((www\.([a-z0-9]([a-z0-9]|-)*[a-z0-9]|[a-z0-9])\.)+([a-z]([a-z0-9]|-)*[a-z0-9]|[a-z])(:[a-zA-Z0-9]*)?(/([a-z0-9\.!$&\'\(\)*+,;=_~:@-]|%[a-f0-9]{2})*)*(\?([a-z0-9\.!$&\'\(\)*+,;=_~:@/?-]|%[a-fA-F0-9]{2})*)?(\#[a-z0-9\.!$&\'\(\)*+,;=_~:@/?-]*)?)(?<![,.;])#i',
  121. '<a href="http://\\1" class="_blanktarget">\\1</a>', $text);
  122. }
  123. if (!empty($ignoretags)) {
  124. $ignoretags = array_reverse($ignoretags); /// Reversed so "progressive" str_replace() will solve some nesting problems.
  125. $text = str_replace(array_keys($ignoretags),$ignoretags,$text);
  126. }
  127. if ($this->get_global_config('embedimages')) {
  128. // now try to inject the images, this code was originally in the mediapluing filter
  129. // this may be useful only if somebody relies on the fact the links in FORMAT_MOODLE get converted
  130. // to URLs which in turn change to real images
  131. $search = '/<a href="([^"]+\.(jpg|png|gif))" class="_blanktarget">([^>]*)<\/a>/is';
  132. $text = preg_replace_callback($search, 'filter_urltolink_img_callback', $text);
  133. }
  134. }
  135. }
  136. /**
  137. * Change links to images into embedded images.
  138. *
  139. * This plugin is intended for automatic conversion of image URLs when FORMAT_MOODLE used.
  140. *
  141. * @param $link
  142. * @return string
  143. */
  144. function filter_urltolink_img_callback($link) {
  145. if ($link[1] !== $link[3]) {
  146. // this is not a link created by this filter, because the url does not match the text
  147. return $link[0];
  148. }
  149. return '<img class="filter_urltolink_image" alt="" src="'.$link[1].'" />';
  150. }