Merge branch 'MDL-41827_master' of git://github.com/dmonllao/moodle
[moodle.git] / admin / tool / generator / classes / site_backend.php
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/>.
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  */
25 defined('MOODLE_INTERNAL') || die();
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 {
36     /**
37      * @var string The course's shortname prefix.
38      */
39     const SHORTNAMEPREFIX = 'testcourse_';
41     /**
42      * @var bool If the debugging level checking was skipped.
43      */
44     protected $bypasscheck;
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     );
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) {
70         // Set parameters.
71         $this->bypasscheck = $bypasscheck;
73         parent::__construct($size, $fixeddataset, $filesizelimit, $progress);
74     }
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     }
89     /**
90      * Runs the entire 'make' process.
91      *
92      * @return int Course id
93      */
94     public function make() {
95         global $DB, $CFG;
97         raise_memory_limit(MEMORY_EXTRA);
99         if ($this->progress && !CLI_SCRIPT) {
100             echo html_writer::start_tag('ul');
101         }
103         $entirestart = microtime(true);
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);
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));
121         // Log total time.
122         $this->log('sitecompleted', round(microtime(true) - $entirestart, 1));
124         if ($this->progress && !CLI_SCRIPT) {
125             echo html_writer::end_tag('ul');
126         }
128         return $lastcourseid;
129     }
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) {
140         // We are in $CFG->dirroot.
141         $command = 'php admin/tool/generator/cli/maketestcourse.php';
143         $options = array(
144             '--shortname="' . $shortname . '"',
145             '--size="' . get_string('shortsize_' . $coursesize, 'tool_generator') . '"'
146         );
148         if (!$this->progress) {
149             $options[] = '--quiet';
150         }
152         if ($this->filesizelimit) {
153             $options[] = '--filesizelimit="' . $this->filesizelimit . '"';
154         }
156         // Extend options.
157         $optionstoextend = array(
158             'fixeddataset' => 'fixeddataset',
159             'bypasscheck' => 'bypasscheck',
160         );
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         }
175         if ($exitcode != 0) {
176             exit($exitcode);
177         }
178     }
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;
188         $params = array();
189         $params['shortnameprefix'] = $DB->sql_like_escape(self::SHORTNAMEPREFIX) . '%';
190         $like = $DB->sql_like('shortname', ':shortnameprefix');
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);
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     }