Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.10.x will end 8 November 2021 (12 months).
  • Bug fixes for security issues in 3.10.x will end 9 May 2022 (18 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.

Differences Between: [Versions 310 and 311] [Versions 310 and 400] [Versions 310 and 401] [Versions 310 and 402] [Versions 310 and 403] [Versions 39 and 310]

   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  /**
  18   * This filter provides automatic linking to database activity entries
  19   * when found inside every Moodle text.
  20   *
  21   * @package    filter
  22   * @subpackage data
  23   * @copyright  2006 Vy-Shane Sin Fat
  24   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  25   */
  26  
  27  defined('MOODLE_INTERNAL') || die();
  28  
  29  /**
  30   * Database activity filtering
  31   */
  32  class filter_data extends moodle_text_filter {
  33  
  34      public function filter($text, array $options = array()) {
  35          global $CFG, $DB, $USER;
  36  
  37          // Trivial-cache - keyed on $cachedcourseid + $cacheduserid.
  38          static $cachedcourseid = null;
  39          static $cacheduserid = null;
  40          static $coursecontentlist = array();
  41          static $sitecontentlist = array();
  42  
  43          static $nothingtodo;
  44  
  45          // Try to get current course.
  46          $coursectx = $this->context->get_course_context(false);
  47          if (!$coursectx) {
  48              // We could be in a course category so no entries for courseid == 0 will be found.
  49              $courseid = 0;
  50          } else {
  51              $courseid = $coursectx->instanceid;
  52          }
  53  
  54          if ($cacheduserid !== $USER->id) {
  55              // Invalidate all caches if the user changed.
  56              $coursecontentlist = array();
  57              $sitecontentlist = array();
  58              $cacheduserid = $USER->id;
  59              $cachedcourseid = $courseid;
  60              $nothingtodo = false;
  61          } else if ($courseid != get_site()->id && $courseid != 0 && $cachedcourseid != $courseid) {
  62              // Invalidate course-level caches if the course id changed.
  63              $coursecontentlist = array();
  64              $cachedcourseid = $courseid;
  65              $nothingtodo = false;
  66          }
  67  
  68          if ($nothingtodo === true) {
  69              return $text;
  70          }
  71  
  72          // If courseid == 0 only site entries will be returned.
  73          if ($courseid == get_site()->id || $courseid == 0) {
  74              $contentlist = & $sitecontentlist;
  75          } else {
  76              $contentlist = & $coursecontentlist;
  77          }
  78  
  79          // Create a list of all the resources to search for. It may be cached already.
  80          if (empty($contentlist)) {
  81              $coursestosearch = $courseid ? array($courseid) : array(); // Add courseid if found
  82              if (get_site()->id != $courseid) { // Add siteid if was not courseid
  83                  $coursestosearch[] = get_site()->id;
  84              }
  85              // We look for text field contents only if have autolink enabled (param1)
  86              list ($coursesql, $params) = $DB->get_in_or_equal($coursestosearch);
  87              $sql = 'SELECT dc.id AS contentid, dr.id AS recordid, dc.content AS content, d.id AS dataid
  88                        FROM {data} d
  89                        JOIN {data_fields} df ON df.dataid = d.id
  90                        JOIN {data_records} dr ON dr.dataid = d.id
  91                        JOIN {data_content} dc ON dc.fieldid = df.id AND dc.recordid = dr.id
  92                       WHERE d.course ' . $coursesql . '
  93                         AND df.type = \'text\'
  94                         AND ' . $DB->sql_compare_text('df.param1', 1) . " = '1'";
  95  
  96              if (!$contents = $DB->get_records_sql($sql, $params)) {
  97                  $nothingtodo = true;
  98                  return $text;
  99              }
 100  
 101              foreach ($contents as $key => $content) {
 102                  // Trim empty or unlinkable concepts
 103                  $currentcontent = trim(strip_tags($content->content));
 104                  if (empty($currentcontent)) {
 105                      unset($contents[$key]);
 106                      continue;
 107                  } else {
 108                      $contents[$key]->content = $currentcontent;
 109                  }
 110  
 111                  // Rule out any small integers.  See bug 1446
 112                  $currentint = intval($currentcontent);
 113                  if ($currentint && (strval($currentint) == $currentcontent) && $currentint < 1000) {
 114                      unset($contents[$key]);
 115                  }
 116              }
 117  
 118              if (empty($contents)) {
 119                  $nothingtodo = true;
 120                  return $text;
 121              }
 122  
 123              usort($contents, 'filter_data::sort_entries_by_length');
 124  
 125              foreach ($contents as $content) {
 126                  $href_tag_begin = '<a class="data autolink dataid'.$content->dataid.'" title="'.$content->content.'" '.
 127                                    'href="'.$CFG->wwwroot.'/mod/data/view.php?d='.$content->dataid.
 128                                    '&amp;rid='.$content->recordid.'">';
 129                  $contentlist[] = new filterobject($content->content, $href_tag_begin, '</a>', false, true);
 130              }
 131  
 132              $contentlist = filter_remove_duplicates($contentlist); // Clean dupes
 133          }
 134          return filter_phrases($text, $contentlist);  // Look for all these links in the text
 135      }
 136  
 137      private static function sort_entries_by_length($content0, $content1) {
 138          $len0 = strlen($content0->content);
 139          $len1 = strlen($content1->content);
 140  
 141          if ($len0 < $len1) {
 142              return 1;
 143          } else if ($len0 > $len1) {
 144              return -1;
 145          } else {
 146              return 0;
 147          }
 148      }
 149  }