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  /**
  18   * Blackboard V5 and V6 question importer.
  19   *
  20   * @package    qformat_blackboard_six
  21   * @copyright  2012 Jean-Michel Vedrine
  22   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23   */
  24  
  25  defined('MOODLE_INTERNAL') || die();
  26  
  27  /**
  28   * Base class question import format for zip files with images
  29   *
  30   * @package    qformat_blackboard_six
  31   * @copyright  2012 Jean-Michel Vedrine
  32   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  33   */
  34  class qformat_blackboard_six_base extends qformat_based_on_xml {
  35      /** @var string path to path to root of image tree in unzipped archive. */
  36      public $filebase = '';
  37      /** @var string path to the temporary directory. */
  38      public $tempdir = '';
  39  
  40      /**
  41       * This plugin provide import
  42       * @return bool true
  43       */
  44      public function provide_import() {
  45          return true;
  46      }
  47  
  48      /**
  49       * Check if the given file is capable of being imported by this plugin.
  50       * As {@link file_storage::mimetype()} may use finfo PHP extension if available,
  51       * the value returned by $file->get_mimetype for a .dat file is not the same on all servers.
  52       * So we must made 2 checks to verify if the plugin can import the file.
  53       * @param stored_file $file the file to check
  54       * @return bool whether this plugin can import the file
  55       */
  56      public function can_import_file($file) {
  57          $mimetypes = array(
  58              mimeinfo('type', '.dat'),
  59              mimeinfo('type', '.zip')
  60          );
  61          return in_array($file->get_mimetype(), $mimetypes) || in_array(mimeinfo('type', $file->get_filename()), $mimetypes);
  62      }
  63  
  64      public function mime_type() {
  65          return mimeinfo('type', '.zip');
  66      }
  67  
  68      /**
  69       * Does any post-processing that may be desired
  70       * Clean the temporary directory if a zip file was imported
  71       * @return bool success
  72       */
  73      public function importpostprocess() {
  74          if ($this->tempdir != '') {
  75              fulldelete($this->tempdir);
  76          }
  77          return true;
  78      }
  79      /**
  80       * Set the path to the root of images tree
  81       * @param string $path path to images root
  82       */
  83      public function set_filebase($path) {
  84          $this->filebase = $path;
  85      }
  86  
  87      /**
  88       * Store an image file in a draft filearea
  89       * @param array $text, if itemid element don't exists it will be created
  90       * @param string $tempdir path to root of image tree
  91       * @param string $filepathinsidetempdir path to image in the tree
  92       * @param string $filename image's name
  93       * @return string new name of the image as it was stored
  94       */
  95      protected function store_file_for_text_field(&$text, $tempdir, $filepathinsidetempdir, $filename) {
  96          global $USER;
  97          $fs = get_file_storage();
  98          if (empty($text['itemid'])) {
  99              $text['itemid'] = file_get_unused_draft_itemid();
 100          }
 101          // As question file areas don't support subdirs,
 102          // convert path to filename.
 103          // So that images with same name can be imported.
 104          $newfilename = clean_param(str_replace('/', '__', $filepathinsidetempdir . '__' . $filename), PARAM_FILE);
 105          $filerecord = array(
 106              'contextid' => context_user::instance($USER->id)->id,
 107              'component' => 'user',
 108              'filearea'  => 'draft',
 109              'itemid'    => $text['itemid'],
 110              'filepath'  => '/',
 111              'filename'  => $newfilename,
 112          );
 113          $fs->create_file_from_pathname($filerecord, $tempdir . '/' . $filepathinsidetempdir . '/' . $filename);
 114          return $newfilename;
 115      }
 116  
 117      /**
 118       * Given an HTML text with references to images files,
 119       * store all images in a draft filearea,
 120       * and return an array with all urls in text recoded,
 121       * format set to FORMAT_HTML, and itemid set to filearea itemid
 122       * @param string $text text to parse and recode
 123       * @return array with keys text, format, itemid.
 124       */
 125      public function text_field($text) {
 126          $data = array();
 127          // Step one, find all file refs then add to array.
 128          preg_match_all('|<img[^>]+src="([^"]*)"|i', $text, $out); // Find all src refs.
 129          $filepaths = array();
 130          foreach ($out[1] as $path) {
 131              $fullpath = $this->filebase . '/' . $path;
 132  
 133              if (is_readable($fullpath) && !in_array($path, $filepaths)) {
 134                  $dirpath = dirname($path);
 135                  $filename = basename($path);
 136                  $newfilename = $this->store_file_for_text_field($data, $this->filebase, $dirpath, $filename);
 137                  $text = preg_replace("|{$path}|", "@@PLUGINFILE@@/" . $newfilename, $text);
 138                  $filepaths[] = $path;
 139              }
 140  
 141          }
 142          $data['text'] = $text;
 143          $data['format'] = FORMAT_HTML;
 144          return $data;
 145      }
 146  
 147      /**
 148       * Same as text_field but text is cleaned.
 149       * @param string $text text to parse and recode
 150       * @return array with keys text, format, itemid.
 151       */
 152      public function cleaned_text_field($text) {
 153          return $this->text_field($this->cleaninput($text));
 154      }
 155  }