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   * tool_generator site backend.
  19   *
  20   * @package tool_generator
  21   * @copyright 2013 David MonllaĆ³
  22   * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23   */
  24  
  25  defined('MOODLE_INTERNAL') || die();
  26  
  27  /**
  28   * Backend code for the site generator.
  29   *
  30   * @package tool_generator
  31   * @copyright 2013 David MonllaĆ³
  32   * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  33   */
  34  class tool_generator_site_backend extends tool_generator_backend {
  35  
  36      /**
  37       * @var string The course's shortname prefix.
  38       */
  39      const SHORTNAMEPREFIX = 'testcourse_';
  40  
  41      /**
  42       * @var bool If the debugging level checking was skipped.
  43       */
  44      protected $bypasscheck;
  45  
  46      /**
  47       * @var array Multidimensional array where the first level is the course size and the second the site size.
  48       */
  49      protected static $sitecourses = array(
  50          array(2, 8, 64, 256, 1024, 4096),
  51          array(1, 4, 8, 16, 32, 64),
  52          array(0, 0, 1, 4, 8, 16),
  53          array(0, 0, 0, 1, 0, 0),
  54          array(0, 0, 0, 0, 1, 0),
  55          array(0, 0, 0, 0, 0, 1)
  56      );
  57  
  58      /**
  59       * Constructs object ready to make the site.
  60       *
  61       * @param int $size Size as numeric index
  62       * @param bool $bypasscheck If debugging level checking was skipped.
  63       * @param bool $fixeddataset To use fixed or random data
  64       * @param int|bool $filesizelimit The max number of bytes for a generated file
  65       * @param bool $progress True if progress information should be displayed
  66       * @return int Course id
  67       */
  68      public function __construct($size, $bypasscheck, $fixeddataset = false, $filesizelimit = false, $progress = true) {
  69  
  70          // Set parameters.
  71          $this->bypasscheck = $bypasscheck;
  72  
  73          parent::__construct($size, $fixeddataset, $filesizelimit, $progress);
  74      }
  75  
  76      /**
  77       * Gets a list of size choices supported by this backend.
  78       *
  79       * @return array List of size (int) => text description for display
  80       */
  81      public static function get_size_choices() {
  82          $options = array();
  83          for ($size = self::MIN_SIZE; $size <= self::MAX_SIZE; $size++) {
  84              $options[$size] = get_string('sitesize_' . $size, 'tool_generator');
  85          }
  86          return $options;
  87      }
  88  
  89      /**
  90       * Runs the entire 'make' process.
  91       *
  92       * @return int Course id
  93       */
  94      public function make() {
  95          global $DB, $CFG;
  96  
  97          raise_memory_limit(MEMORY_EXTRA);
  98  
  99          if ($this->progress && !CLI_SCRIPT) {
 100              echo html_writer::start_tag('ul');
 101          }
 102  
 103          $entirestart = microtime(true);
 104  
 105          // Create courses.
 106          $prevchdir = getcwd();
 107          chdir($CFG->dirroot);
 108          $ncourse = self::get_last_testcourse_id();
 109          foreach (self::$sitecourses as $coursesize => $ncourses) {
 110              for ($i = 1; $i <= $ncourses[$this->size]; $i++) {
 111                  // Non language-dependant shortname.
 112                  $ncourse++;
 113                  $this->run_create_course(self::SHORTNAMEPREFIX . $ncourse, $coursesize);
 114              }
 115          }
 116          chdir($prevchdir);
 117  
 118          // Store last course id to return it (will be the bigger one).
 119          $lastcourseid = $DB->get_field('course', 'id', array('shortname' => self::SHORTNAMEPREFIX . $ncourse));
 120  
 121          // Log total time.
 122          $this->log('sitecompleted', round(microtime(true) - $entirestart, 1));
 123  
 124          if ($this->progress && !CLI_SCRIPT) {
 125              echo html_writer::end_tag('ul');
 126          }
 127  
 128          return $lastcourseid;
 129      }
 130  
 131      /**
 132       * Creates a course with the specified shortname, coursesize and the provided maketestsite options.
 133       *
 134       * @param string $shortname The course shortname
 135       * @param int $coursesize One of the possible course sizes.
 136       * @return void
 137       */
 138      protected function run_create_course($shortname, $coursesize) {
 139  
 140          // We are in $CFG->dirroot.
 141          $command = 'php admin/tool/generator/cli/maketestcourse.php';
 142  
 143          $options = array(
 144              '--shortname="' . $shortname . '"',
 145              '--size="' . get_string('shortsize_' . $coursesize, 'tool_generator') . '"'
 146          );
 147  
 148          if (!$this->progress) {
 149              $options[] = '--quiet';
 150          }
 151  
 152          if ($this->filesizelimit) {
 153              $options[] = '--filesizelimit="' . $this->filesizelimit . '"';
 154          }
 155  
 156          // Extend options.
 157          $optionstoextend = array(
 158              'fixeddataset' => 'fixeddataset',
 159              'bypasscheck' => 'bypasscheck',
 160          );
 161  
 162          // Getting an options string.
 163          foreach ($optionstoextend as $attribute => $option) {
 164              if (!empty($this->{$attribute})) {
 165                  $options[] = '--' . $option;
 166              }
 167          }
 168          $options = implode(' ', $options);
 169          if ($this->progress) {
 170              system($command . ' ' . $options, $exitcode);
 171          } else {
 172              passthru($command . ' ' . $options, $exitcode);
 173          }
 174  
 175          if ($exitcode != 0) {
 176              exit($exitcode);
 177          }
 178      }
 179  
 180      /**
 181       * Obtains the last unique sufix (numeric) using the test course prefix.
 182       *
 183       * @return int The last generated numeric value.
 184       */
 185      protected static function get_last_testcourse_id() {
 186          global $DB;
 187  
 188          $params = array();
 189          $params['shortnameprefix'] = $DB->sql_like_escape(self::SHORTNAMEPREFIX) . '%';
 190          $like = $DB->sql_like('shortname', ':shortnameprefix');
 191  
 192          if (!$testcourses = $DB->get_records_select('course', $like, $params, '', 'shortname')) {
 193              return 0;
 194          }
 195          // SQL order by is not appropiate here as is ordering strings.
 196          $shortnames = array_keys($testcourses);
 197          core_collator::asort($shortnames, core_collator::SORT_NATURAL);
 198          $shortnames = array_reverse($shortnames);
 199  
 200          // They come ordered by shortname DESC, so non-numeric values will be the first ones.
 201          $prefixnchars = strlen(self::SHORTNAMEPREFIX);
 202          foreach ($shortnames as $shortname) {
 203              $sufix = substr($shortname, $prefixnchars);
 204              if (preg_match('/^[\d]+$/', $sufix)) {
 205                  return $sufix;
 206              }
 207          }
 208          // If all sufixes are not numeric this is the first make test site run.
 209          return 0;
 210      }
 211  
 212  }