Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
 
3
// This file is part of Moodle - http://moodle.org/
4
//
5
// Moodle is free software: you can redistribute it and/or modify
6
// it under the terms of the GNU General Public License as published by
7
// the Free Software Foundation, either version 3 of the License, or
8
// (at your option) any later version.
9
//
10
// Moodle is distributed in the hope that it will be useful,
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
// GNU General Public License for more details.
14
//
15
// You should have received a copy of the GNU General Public License
16
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
17
 
18
/**
19
 * Provides support for the conversion of moodle1 backup to the moodle2 format
20
 *
21
 * @package   mod_workshop
22
 * @copyright 2011 David Mudrak <david@moodle.com>
23
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24
 */
25
 
26
defined('MOODLE_INTERNAL') || die();
27
 
28
/**
29
 * Workshop conversion handler
30
 */
31
class moodle1_mod_workshop_handler extends moodle1_mod_handler {
32
 
33
    /** @var array the temporary in-memory cache for the current <MOD> contents */
34
    protected $currentworkshop = null;
35
 
36
    /** @var array in-memory cache for the course module information for the current workshop  */
37
    protected $currentcminfo = null;
38
 
39
    /** @var array the mapping of legacy elementno => newelementid for the current workshop */
40
    protected $newelementids = array();
41
 
42
    /** @var moodle1_file_manager for the current workshop */
43
    protected $fileman = null;
44
 
45
    /** @var moodle1_inforef_manager */
46
    protected $inforefman = null;
47
 
48
    /** @var array list of moodle1_workshopform_handler instances */
49
    private $strategyhandlers = null;
50
 
51
    /** @var int parent id for the rubric level */
52
    private $currentelementid = null;
53
 
54
    /**
55
     * Declare the paths in moodle.xml we are able to convert
56
     *
57
     * The method returns list of {@link convert_path} instances. For each path returned,
58
     * at least one of on_xxx_start(), process_xxx() and on_xxx_end() methods must be
59
     * defined. The method process_xxx() is not executed if the associated path element is
60
     * empty (i.e. it contains none elements or sub-paths only).
61
     *
62
     * Note that the path /MOODLE_BACKUP/COURSE/MODULES/MOD/WORKSHOP does not
63
     * actually exist in the file. The last element with the module name was
64
     * appended by the moodle1_converter class.
65
     *
66
     * @return array of {@link convert_path} instances
67
     */
68
    public function get_paths() {
69
        return array(
70
            new convert_path('workshop', '/MOODLE_BACKUP/COURSE/MODULES/MOD/WORKSHOP'),
71
            new convert_path('workshop_elements', '/MOODLE_BACKUP/COURSE/MODULES/MOD/WORKSHOP/ELEMENTS'),
72
            new convert_path(
73
                'workshop_element', '/MOODLE_BACKUP/COURSE/MODULES/MOD/WORKSHOP/ELEMENTS/ELEMENT',
74
                array(
75
                    'dropfields' => array(
76
                        'stddev',
77
                        'totalassessments',
78
                    ),
79
                )
80
            ),
81
            new convert_path('workshop_element_rubric', '/MOODLE_BACKUP/COURSE/MODULES/MOD/WORKSHOP/ELEMENTS/ELEMENT/RUBRICS/RUBRIC'),
82
        );
83
    }
84
 
85
    /**
86
     * This is executed every time we have one /MOODLE_BACKUP/COURSE/MODULES/MOD/WORKSHOP
87
     * data available
88
     */
89
    public function process_workshop($data, $raw) {
90
 
91
        // re-use the upgrade function to convert workshop record
92
        $fakerecord = (object)$data;
93
        $fakerecord->course = 12345678;
94
        $this->currentworkshop = (array)workshop_upgrade_transform_instance($fakerecord);
95
        unset($this->currentworkshop['course']);
96
 
97
        // add the new fields with the default values
98
        $this->currentworkshop['id']                        = $data['id'];
99
        $this->currentworkshop['evaluation']                = 'best';
100
        $this->currentworkshop['examplesmode']              = workshop::EXAMPLES_VOLUNTARY;
101
        $this->currentworkshop['gradedecimals']             = 0;
102
        $this->currentworkshop['instructauthors']           = '';
103
        $this->currentworkshop['instructauthorsformat']     = FORMAT_HTML;
104
        $this->currentworkshop['instructreviewers']         = '';
105
        $this->currentworkshop['instructreviewersformat']   = FORMAT_HTML;
106
        $this->currentworkshop['latesubmissions']           = 0;
107
        $this->currentworkshop['conclusion']                = '';
108
        $this->currentworkshop['conclusionformat']          = FORMAT_HTML;
109
 
110
        foreach (array('submissionend', 'submissionstart', 'assessmentend', 'assessmentstart') as $field) {
111
            if (!array_key_exists($field, $this->currentworkshop)) {
112
                $this->currentworkshop[$field] = null;
113
            }
114
        }
115
 
116
        // get the course module id and context id
117
        $instanceid          = $data['id'];
118
        $this->currentcminfo = $this->get_cminfo($instanceid);
119
        $moduleid            = $this->currentcminfo['id'];
120
        $contextid           = $this->converter->get_contextid(CONTEXT_MODULE, $moduleid);
121
 
122
        // get a fresh new inforef manager for this instance
123
        $this->inforefman = $this->converter->get_inforef_manager('activity', $moduleid);
124
 
125
        // get a fresh new file manager for this instance
126
        $this->fileman = $this->converter->get_file_manager($contextid, 'mod_workshop');
127
 
128
        // convert course files embedded into the intro
129
        $this->fileman->filearea = 'intro';
130
        $this->fileman->itemid   = 0;
131
        $this->currentworkshop['intro'] = moodle1_converter::migrate_referenced_files($this->currentworkshop['intro'], $this->fileman);
132
 
133
        // write workshop.xml
134
        $this->open_xml_writer("activities/workshop_{$moduleid}/workshop.xml");
135
        $this->xmlwriter->begin_tag('activity', array('id' => $instanceid, 'moduleid' => $moduleid,
136
            'modulename' => 'workshop', 'contextid' => $contextid));
137
        $this->xmlwriter->begin_tag('workshop', array('id' => $instanceid));
138
 
139
        foreach ($this->currentworkshop as $field => $value) {
140
            if ($field <> 'id') {
141
                $this->xmlwriter->full_tag($field, $value);
142
            }
143
        }
144
 
145
        return $this->currentworkshop;
146
    }
147
 
148
    /**
149
     * This is executed when the parser reaches <ELEMENTS>
150
     *
151
     * The dimensions definition follows. One of the grading strategy subplugins
152
     * will append dimensions data in {@link self::process_workshop_element()}
153
     */
154
    public function on_workshop_elements_start() {
155
 
156
        $this->xmlwriter->begin_tag('subplugin_workshopform_'.$this->currentworkshop['strategy'].'_workshop');
157
 
158
        // inform the strategy handler that a new workshop instance is being processed
159
        $handler = $this->get_strategy_handler($this->currentworkshop['strategy']);
160
        $handler->use_xml_writer($this->xmlwriter);
161
        $handler->on_elements_start();
162
    }
163
 
164
    /**
165
     * Processes one <ELEMENT> tag from moodle.xml
166
     */
167
    public function process_workshop_element($data, $raw) {
168
 
169
        // generate artificial element id and remember it for later usage
170
        $data['id'] = $this->converter->get_nextid();
171
        $this->currentelementid = $data['id'];
172
        $this->newelementids[$data['elementno']] = $data['id'];
173
 
174
        // let the strategy subplugin do whatever it needs to
175
        $handler = $this->get_strategy_handler($this->currentworkshop['strategy']);
176
        return $handler->process_legacy_element($data, $raw);
177
    }
178
 
179
    /**
180
     * Processes one <RUBRIC> tag from moodle.xml
181
     */
182
    public function process_workshop_element_rubric($data, $raw) {
183
        if ($this->currentworkshop['strategy'] == 'rubric') {
184
            $handler = $this->get_strategy_handler('rubric');
185
            $data['elementid'] = $this->currentelementid;
186
            $handler->process_legacy_rubric($data, $raw);
187
        }
188
    }
189
 
190
    /**
191
     * This is executed when the parser reaches </ELEMENT>
192
     */
193
    public function on_workshop_element_end() {
194
        // give the strategy handlers a chance to write what they need
195
        $handler = $this->get_strategy_handler($this->currentworkshop['strategy']);
196
        $handler->on_legacy_element_end();
197
    }
198
 
199
    /**
200
     * This is executed when the parser reaches </ELEMENTS>
201
     */
202
    public function on_workshop_elements_end() {
203
        // give the strategy hanlders last chance to write what they need
204
        $handler = $this->get_strategy_handler($this->currentworkshop['strategy']);
205
        $handler->on_elements_end();
206
 
207
        // close the dimensions definition
208
        $this->xmlwriter->end_tag('subplugin_workshopform_'.$this->currentworkshop['strategy'].'_workshop');
209
 
210
        // as a temporary hack, we just write empty wrappers for the rest of data
211
        $this->write_xml('examplesubmissions', array());
212
        $this->write_xml('submissions', array());
213
        $this->write_xml('aggregations', array());
214
    }
215
 
216
    /**
217
     * This is executed when the parser reaches </MOD>
218
     */
219
    public function on_workshop_end() {
220
        // close workshop.xml
221
        $this->xmlwriter->end_tag('workshop');
222
        $this->xmlwriter->end_tag('activity');
223
        $this->close_xml_writer();
224
 
225
        // write inforef.xml
226
        $this->inforefman->add_refs('file', $this->fileman->get_fileids());
227
        $moduleid = $this->currentcminfo['id'];
228
        $this->open_xml_writer("activities/workshop_{$moduleid}/inforef.xml");
229
        $this->inforefman->write_refs($this->xmlwriter);
230
        $this->close_xml_writer();
231
 
232
        // get ready for the next instance
233
        $this->currentworkshop = null;
234
        $this->currentcminfo   = null;
235
        $this->newelementids   = array();
236
    }
237
 
238
    /**
239
     * Provides access to the current <workshop> data
240
     *
241
     * @return array|null
242
     */
243
    public function get_current_workshop() {
244
        return $this->currentworkshop;
245
    }
246
 
247
    /**
248
     * Provides access to the instance's inforef manager
249
     *
250
     * @return moodle1_inforef_manager
251
     */
252
    public function get_inforef_manager() {
253
        return $this->inforefman;
254
    }
255
 
256
    /// internal implementation details follow /////////////////////////////////
257
 
258
    /**
259
     * Factory method returning the handler of the given grading strategy subplugin
260
     *
261
     * @param string $strategy the name of the grading strategy
262
     * @throws moodle1_convert_exception
263
     * @return moodle1_workshopform_handler the instance of the handler
264
     */
265
    protected function get_strategy_handler($strategy) {
266
        global $CFG; // we include other files here
267
 
268
        if (is_null($this->strategyhandlers)) {
269
            $this->strategyhandlers = array();
270
            $subplugins = core_component::get_plugin_list('workshopform');
271
            foreach ($subplugins as $name => $dir) {
272
                $handlerfile  = $dir.'/backup/moodle1/lib.php';
273
                $handlerclass = "moodle1_workshopform_{$name}_handler";
274
                if (!file_exists($handlerfile)) {
275
                    continue;
276
                }
277
                require_once($handlerfile);
278
 
279
                if (!class_exists($handlerclass)) {
280
                    throw new moodle1_convert_exception('missing_handler_class', $handlerclass);
281
                }
282
                $this->log('preparing workshop grading strategy handler', backup::LOG_DEBUG, $handlerclass);
283
                $this->strategyhandlers[$name] = new $handlerclass($this, $name);
284
                if (!$this->strategyhandlers[$name] instanceof moodle1_workshopform_handler) {
285
                    throw new moodle1_convert_exception('wrong_handler_class', get_class($this->strategyhandlers[$name]));
286
                }
287
            }
288
        }
289
 
290
        if (!isset($this->strategyhandlers[$strategy])) {
291
            throw new moodle1_convert_exception('usupported_subplugin', 'workshopform_'.$strategy);
292
        }
293
 
294
        return $this->strategyhandlers[$strategy];
295
    }
296
}
297
 
298
 
299
/**
300
 * Base class for the grading strategy subplugin handler
301
 */
302
abstract class moodle1_workshopform_handler extends moodle1_submod_handler {
303
 
304
    /**
305
     * @param moodle1_mod_handler $workshophandler the handler of a module we are subplugin of
306
     * @param string $subpluginname the name of the subplugin
307
     */
308
    public function __construct(moodle1_mod_handler $workshophandler, $subpluginname) {
309
        parent::__construct($workshophandler, 'workshopform', $subpluginname);
310
    }
311
 
312
    /**
313
     * Provides a xml_writer instance to this workshopform handler
314
     *
315
     * @param xml_writer $xmlwriter
316
     */
317
    public function use_xml_writer(xml_writer $xmlwriter) {
318
        $this->xmlwriter = $xmlwriter;
319
    }
320
 
321
    /**
322
     * Called when we reach <ELEMENTS>
323
     *
324
     * Gives the handler a chance to prepare for a new workshop instance
325
     */
326
    public function on_elements_start() {
327
        // do nothing by default
328
    }
329
 
330
    /**
331
     * Called everytime when legacy <ELEMENT> data are available
332
     *
333
     * @param array $data legacy element data
334
     * @param array $raw raw element data
335
     *
336
     * @return array converted
337
     */
338
    public function process_legacy_element(array $data, array $raw) {
339
        return $data;
340
    }
341
 
342
    /**
343
     * Called when we reach </ELEMENT>
344
     */
345
    public function on_legacy_element_end() {
346
        // do nothing by default
347
    }
348
 
349
    /**
350
     * Called when we reach </ELEMENTS>
351
     */
352
    public function on_elements_end() {
353
        // do nothing by default
354
    }
355
}
356
 
357
/**
358
 * Given a record containing data from 1.9 workshop table, returns object containing data as should be saved in 2.0 workshop table
359
 *
360
 * @param stdClass $old record from 1.9 workshop table
361
 * @return stdClass
362
 */
363
function workshop_upgrade_transform_instance(stdClass $old) {
364
    global $CFG;
365
    require_once(__DIR__ . '/../../locallib.php');
366
 
367
    $new                = new stdClass();
368
    $new->course        = $old->course;
369
    $new->name          = $old->name;
370
    $new->intro         = $old->description;
371
    $new->introformat   = $old->format;
372
    if ($old->nattachments == 0) {
373
        // Convert to the new method for disabling file submissions.
374
        $new->submissiontypefile = WORKSHOP_SUBMISSION_TYPE_DISABLED;
375
        $new->submissiontypetext = WORKSHOP_SUBMISSION_TYPE_REQUIRED;
376
        $new->nattachments = 1;
377
    } else {
378
        $new->nattachments  = $old->nattachments;
379
    }
380
    $new->maxbytes      = $old->maxbytes;
381
    $new->grade         = $old->grade;
382
    $new->gradinggrade  = $old->gradinggrade;
383
    $new->phase         = workshop::PHASE_CLOSED;
384
    $new->timemodified  = time();
385
    if ($old->ntassessments > 0) {
386
        $new->useexamples = 1;
387
    } else {
388
        $new->useexamples = 0;
389
    }
390
    $new->usepeerassessment = 1;
391
    $new->useselfassessment = $old->includeself;
392
    switch ($old->gradingstrategy) {
393
    case 0: // 'notgraded' - renamed
394
        $new->strategy = 'comments';
395
        break;
396
    case 1: // 'accumulative'
397
        $new->strategy = 'accumulative';
398
        break;
399
    case 2: // 'errorbanded' - renamed
400
        $new->strategy = 'numerrors';
401
        break;
402
    case 3: // 'criterion' - will be migrated into 'rubric'
403
        $new->strategy = 'rubric';
404
        break;
405
    case 4: // 'rubric'
406
        $new->strategy = 'rubric';
407
        break;
408
    }
409
    if ($old->submissionstart < $old->submissionend) {
410
        $new->submissionstart = $old->submissionstart;
411
        $new->submissionend   = $old->submissionend;
412
    }
413
    if ($old->assessmentstart < $old->assessmentend) {
414
        $new->assessmentstart = $old->assessmentstart;
415
        $new->assessmentend   = $old->assessmentend;
416
    }
417
 
418
    return $new;
419
}