Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.
   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   * @package   moodlecore
  18   * @subpackage backup-imscc
  19   * @copyright 2009 Mauro Rondinelli (mauro.rondinelli [AT] uvcms.com)
  20   * @copyright 2011 Darko Miletic (dmiletic@moodlerooms.com)
  21   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  22   */
  23  
  24  defined('MOODLE_INTERNAL') or die('Direct access to this script is forbidden.');
  25  
  26  class entities {
  27      /**
  28       * Prepares convert for inclusion into XML
  29       *
  30       * @param string $value
  31       * @return string
  32       */
  33      public static function safexml($value) {
  34          $result = htmlspecialchars(html_entity_decode($value, ENT_QUOTES, 'UTF-8'),
  35                                     ENT_NOQUOTES,
  36                                     'UTF-8',
  37                                     false);
  38          return $result;
  39      }
  40  
  41      protected function prepare_content($content) {
  42          $result = $content;
  43          if (empty($result)) {
  44              return '';
  45          }
  46          $encoding = null;
  47          $xml_error = new libxml_errors_mgr();
  48          $dom = new DOMDocument();
  49          $dom->validateOnParse = false;
  50          $dom->strictErrorChecking = false;
  51          if ($dom->loadHTML($content)) {
  52              $encoding = $dom->xmlEncoding;
  53          }
  54          if (empty($encoding)) {
  55              $encoding = mb_detect_encoding($content, 'auto', true);
  56          }
  57          if (!empty($encoding) && !mb_check_encoding($content, 'UTF-8')) {
  58              $result = mb_convert_encoding($content, 'UTF-8', $encoding);
  59          }
  60  
  61          // See if we can strip off body tag and anything outside of it.
  62          foreach (array('body', 'html') as $tagname) {
  63              $regex = str_replace('##', $tagname, "/<##[^>]*>(.+)<\/##>/is");
  64              if (preg_match($regex, $result, $matches)) {
  65                  $result = $matches[1];
  66                  break;
  67              }
  68          }
  69          return $result;
  70      }
  71  
  72      public function load_xml_resource($path_to_file) {
  73  
  74          $resource = new DOMDocument();
  75  
  76          cc2moodle::log_action('Load the XML resource file: '.$path_to_file);
  77  
  78          if (!$resource->load($path_to_file)) {
  79              cc2moodle::log_action('Cannot load the XML resource file: ' . $path_to_file, false);
  80          }
  81  
  82          return $resource;
  83      }
  84  
  85      public function update_sources($html, $root_path = '') {
  86  
  87          $document = $this->load_html($html);
  88  
  89          $tags = array('img' => 'src' , 'a' => 'href');
  90  
  91          foreach ($tags as $tag => $attribute) {
  92  
  93              $elements = $document->getElementsByTagName($tag);
  94  
  95              foreach ($elements as $element) {
  96  
  97                  $attribute_value = $element->getAttribute($attribute);
  98                  $protocol = parse_url($attribute_value, PHP_URL_SCHEME);
  99  
 100                  if (empty($protocol)) {
 101                      $attribute_value = str_replace("\$IMS-CC-FILEBASE\$", "", $attribute_value);
 102                      $attribute_value = $this->full_path($root_path . "/" . $attribute_value, "/");
 103                      $attribute_value = "\$@FILEPHP@\$" . "/" . $attribute_value;
 104                  }
 105  
 106                  $element->setAttribute($attribute, $attribute_value);
 107              }
 108          }
 109  
 110          $html = $this->html_insidebody($document);
 111  
 112          return $html;
 113      }
 114  
 115      public function full_path($path, $dir_sep = DIRECTORY_SEPARATOR) {
 116  
 117          $token = '$IMS-CC-FILEBASE$';
 118          $path = str_replace($token, '', $path);
 119  
 120          if (is_string($path) && ($path != '')) {
 121              $dot_dir = '.';
 122              $up_dir = '..';
 123              $length = strlen($path);
 124              $rtemp = trim($path);
 125              $start = strrpos($path, $dir_sep);
 126              $can_continue = ($start !== false);
 127              $result = $can_continue ? '' : $path;
 128              $rcount = 0;
 129  
 130              while ($can_continue) {
 131  
 132                  $dir_part = ($start !== false) ? substr($rtemp, $start + 1, $length - $start) : $rtemp;
 133                  $can_continue = ($dir_part !== false);
 134  
 135                  if ($can_continue) {
 136                      if ($dir_part != $dot_dir) {
 137                          if ($dir_part == $up_dir) {
 138                              $rcount++;
 139                          } else {
 140                              if ($rcount > 0) {
 141                                  $rcount --;
 142                              } else {
 143                                  $result = ($result == '') ? $dir_part : $dir_part . $dir_sep . $result;
 144                              }
 145                          }
 146                      }
 147                      $rtemp = substr($path, 0, $start);
 148                      $start = strrpos($rtemp, $dir_sep);
 149                      $can_continue = (($start !== false) || (strlen($rtemp) > 0));
 150                  }
 151              }
 152          }
 153  
 154          return $result;
 155      }
 156  
 157      public function include_titles ($html) {
 158  
 159          $document = $this->load_html($html);
 160  
 161          $images = $document->getElementsByTagName('img');
 162  
 163          foreach ($images as $image) {
 164  
 165              $src = $image->getAttribute('src');
 166              $alt = $image->getAttribute('alt');
 167              $title = $image->getAttribute('title');
 168  
 169              $filename = pathinfo($src);
 170              $filename = $filename['filename'];
 171  
 172              $alt = empty($alt) ? $filename : $alt;
 173              $title = empty($title) ? $filename : $title;
 174  
 175              $image->setAttribute('alt', $alt);
 176              $image->setAttribute('title', $title);
 177          }
 178  
 179          $html = $this->html_insidebody($document);
 180  
 181          return $html;
 182      }
 183  
 184      public function get_external_xml ($identifier) {
 185  
 186          $xpath = cc2moodle::newx_path(cc2moodle::$manifest, cc2moodle::$namespaces);
 187  
 188          $files = $xpath->query('/imscc:manifest/imscc:resources/imscc:resource[@identifier="'.
 189              $identifier.'"]/imscc:file/@href');
 190  
 191          if (empty($files)) {
 192              $response = '';
 193          } else {
 194              $response = $files->item(0)->nodeValue;
 195          }
 196  
 197          return $response;
 198      }
 199  
 200      public function move_files($files, $destination_folder) {
 201          global $CFG, $OUTPUT;
 202  
 203          if (!empty($files)) {
 204  
 205              foreach ($files as $file) {
 206                  $source = cc2moodle::$path_to_manifest_folder . DIRECTORY_SEPARATOR . $file;
 207                  $destination = $destination_folder . DIRECTORY_SEPARATOR . $file;
 208  
 209                  $destination_directory = dirname($destination);
 210  
 211                  cc2moodle::log_action('Copy the file: ' . $source . ' to ' . $destination);
 212  
 213                  if (!file_exists($destination_directory)) {
 214                      mkdir($destination_directory, $CFG->directorypermissions, true);
 215                  }
 216  
 217                  $copy_success = true;
 218                  if (is_file($source)) {
 219                      $copy_success = @copy($source, $destination);
 220                  }
 221  
 222                  if (!$copy_success) {
 223                      echo $OUTPUT->notification('WARNING: Cannot copy the file ' . $source . ' to ' . $destination);
 224                      cc2moodle::log_action('Cannot copy the file ' . $source . ' to ' . $destination, false);
 225                  }
 226              }
 227          }
 228      }
 229  
 230      protected function get_all_files () {
 231          global $CFG;
 232  
 233          $all_files = array();
 234  
 235          $xpath = cc2moodle::newx_path(cc2moodle::$manifest, cc2moodle::$namespaces);
 236  
 237          foreach (cc2moodle::$restypes as $type) {
 238  
 239              $files = $xpath->query('/imscc:manifest/imscc:resources/imscc:resource[@type="' . $type . '"]/imscc:file/@href');
 240  
 241              if (!empty($files) && ($files->length > 0)) {
 242                  foreach ($files as $file) {
 243                      // Omit html files.
 244                      $ext = strtolower(pathinfo($file->nodeValue, PATHINFO_EXTENSION));
 245                      if (in_array($ext, array('html', 'htm', 'xhtml'))) {
 246                          continue;
 247                      }
 248                      $all_files[] = $file->nodeValue;
 249                  }
 250              }
 251              unset($files);
 252          }
 253  
 254          // Are there any labels?
 255          $xquery = "//imscc:item/imscc:item/imscc:item[imscc:title][not(@identifierref)]";
 256          $labels = $xpath->query($xquery);
 257          if (!empty($labels) && ($labels->length > 0)) {
 258              $tname = 'course_files';
 259              $dpath = cc2moodle::$path_to_manifest_folder . DIRECTORY_SEPARATOR . $tname;
 260              $rfpath = 'files.gif';
 261              $fpath = $dpath . DIRECTORY_SEPARATOR . $rfpath;
 262  
 263              if (!file_exists($dpath)) {
 264                  mkdir($dpath, $CFG->directorypermissions, true);
 265              }
 266              // Copy the folder.gif file.
 267              $folder_gif = "{$CFG->dirroot}/pix/i/files.gif";
 268              copy($folder_gif, $fpath);
 269              $all_files[] = $rfpath;
 270          }
 271  
 272          $all_files = empty($all_files) ? '' : $all_files;
 273  
 274          return $all_files;
 275      }
 276  
 277      public function move_all_files() {
 278  
 279          $files = $this->get_all_files();
 280  
 281          if (!empty($files)) {
 282              $this->move_files($files, cc2moodle::$path_to_manifest_folder . DIRECTORY_SEPARATOR . 'course_files', true);
 283          }
 284  
 285      }
 286  
 287      /**
 288       * @param string $html
 289       * @return DOMDocument
 290       */
 291      private function load_html($html) {
 292          // Need to make sure that the html passed has charset meta tag.
 293          $metatag = '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />';
 294          if (strpos($html, $metatag) === false) {
 295              $html = '<html><head>'.$metatag.'</head><body>'.$html.'</body></html>';
 296          }
 297  
 298          $document = new DOMDocument();
 299          @$document->loadHTML($html);
 300  
 301          return $document;
 302      }
 303  
 304      /**
 305       * @param DOMDocument $domdocument
 306       * @return string
 307       */
 308      private function html_insidebody($domdocument) {
 309          $html = '';
 310          $bodyitems = $domdocument->getElementsByTagName('body');
 311          if ($bodyitems->length > 0) {
 312              $body = $bodyitems->item(0);
 313              $html = str_ireplace(array('<body>', '</body>'), '', $body->C14N());
 314          }
 315  
 316          return $html;
 317      }
 318  
 319      public function generate_random_string ($length = 6) {
 320  
 321          $response = '';
 322          $source = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
 323  
 324          if ($length > 0) {
 325  
 326              $response = '';
 327              $source = str_split($source, 1);
 328  
 329              for ($i = 1; $i <= $length; $i++) {
 330                  $num = mt_rand(1, count($source));
 331                  $response .= $source[$num - 1];
 332              }
 333          }
 334  
 335          return $response;
 336      }
 337  
 338      public function truncate_text($text, $max, $remove_html) {
 339  
 340          if ($max > 10) {
 341              $text = substr($text, 0, ($max - 6)) . ' [...]';
 342          } else {
 343              $text = substr($text, 0, $max);
 344          }
 345  
 346          $text = $remove_html ? strip_tags($text) : $text;
 347  
 348          return $text;
 349      }
 350  }