Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
// This file is part of the customcert module for 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
 * This file contains the customcert element image's core interaction API.
19
 *
20
 * @package    customcertelement_image
21
 * @copyright  2013 Mark Nelson <markn@moodle.com>
22
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23
 */
24
 
25
namespace customcertelement_image;
26
 
27
/**
28
 * The customcert element image's core interaction API.
29
 *
30
 * @package    customcertelement_image
31
 * @copyright  2013 Mark Nelson <markn@moodle.com>
32
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
33
 */
34
class element extends \mod_customcert\element {
35
 
36
    /**
37
     * @var array The file manager options.
38
     */
39
    protected $filemanageroptions = [];
40
 
41
    /**
42
     * Constructor.
43
     *
44
     * @param \stdClass $element the element data
45
     */
46
    public function __construct($element) {
47
        global $COURSE;
48
 
49
        $this->filemanageroptions = [
50
            'maxbytes' => $COURSE->maxbytes,
51
            'subdirs' => 1,
52
            'accepted_types' => 'image',
53
        ];
54
 
55
        parent::__construct($element);
56
    }
57
 
58
    /**
59
     * This function renders the form elements when adding a customcert element.
60
     *
61
     * @param \MoodleQuickForm $mform the edit_form instance
62
     */
63
    public function render_form_elements($mform) {
64
        $mform->addElement('select', 'fileid', get_string('image', 'customcertelement_image'), self::get_images());
65
 
66
        \mod_customcert\element_helper::render_form_element_width($mform);
67
 
68
        \mod_customcert\element_helper::render_form_element_height($mform);
69
 
70
        $alphachannelvalues = [
71
            '0' => 0,
72
            '0.1' => 0.1,
73
            '0.2' => 0.2,
74
            '0.3' => 0.3,
75
            '0.4' => 0.4,
76
            '0.5' => 0.5,
77
            '0.6' => 0.6,
78
            '0.7' => 0.7,
79
            '0.8' => 0.8,
80
            '0.9' => 0.9,
81
            '1' => 1,
82
        ];
83
        $mform->addElement('select', 'alphachannel', get_string('alphachannel', 'customcertelement_image'), $alphachannelvalues);
84
        $mform->setType('alphachannel', PARAM_FLOAT);
85
        $mform->setDefault('alphachannel', 1);
86
        $mform->addHelpButton('alphachannel', 'alphachannel', 'customcertelement_image');
87
 
88
        if (get_config('customcert', 'showposxy')) {
89
            \mod_customcert\element_helper::render_form_element_position($mform);
90
        }
91
 
92
        $mform->addElement('filemanager', 'customcertimage', get_string('uploadimage', 'customcert'), '',
93
            $this->filemanageroptions);
94
    }
95
 
96
    /**
97
     * Performs validation on the element values.
98
     *
99
     * @param array $data the submitted data
100
     * @param array $files the submitted files
101
     * @return array the validation errors
102
     */
103
    public function validate_form_elements($data, $files) {
104
        // Array to return the errors.
105
        $errors = [];
106
 
107
        // Validate the width.
108
        $errors += \mod_customcert\element_helper::validate_form_element_width($data);
109
 
110
        // Validate the height.
111
        $errors += \mod_customcert\element_helper::validate_form_element_height($data);
112
 
113
        // Validate the position.
114
        if (get_config('customcert', 'showposxy')) {
115
            $errors += \mod_customcert\element_helper::validate_form_element_position($data);
116
        }
117
 
118
        return $errors;
119
    }
120
 
121
    /**
122
     * Handles saving the form elements created by this element.
123
     * Can be overridden if more functionality is needed.
124
     *
125
     * @param \stdClass $data the form data
126
     * @return bool true of success, false otherwise.
127
     */
128
    public function save_form_elements($data) {
129
        global $COURSE, $SITE;
130
 
131
        // Set the context.
132
        if ($COURSE->id == $SITE->id) {
133
            $context = \context_system::instance();
134
        } else {
135
            $context = \context_course::instance($COURSE->id);
136
        }
137
 
138
        // Handle file uploads.
139
        \mod_customcert\certificate::upload_files($data->customcertimage, $context->id);
140
 
141
        return parent::save_form_elements($data);
142
    }
143
 
144
    /**
145
     * This will handle how form data will be saved into the data column in the
146
     * customcert_elements table.
147
     *
148
     * @param \stdClass $data the form data
149
     * @return string the json encoded array
150
     */
151
    public function save_unique_data($data) {
152
        $arrtostore = [
153
            'width' => !empty($data->width) ? (int) $data->width : 0,
154
            'height' => !empty($data->height) ? (int) $data->height : 0,
155
        ];
156
 
157
        if (isset($data->alphachannel)) {
158
            $arrtostore['alphachannel'] = (float) $data->alphachannel;
159
        }
160
 
161
        if (!empty($data->fileid)) {
162
            // Array of data we will be storing in the database.
163
            $fs = get_file_storage();
164
            if ($file = $fs->get_file_by_id($data->fileid)) {
165
                $arrtostore += [
166
                    'contextid' => $file->get_contextid(),
167
                    'filearea' => $file->get_filearea(),
168
                    'itemid' => $file->get_itemid(),
169
                    'filepath' => $file->get_filepath(),
170
                    'filename' => $file->get_filename(),
171
                ];
172
            }
173
        }
174
 
175
        return json_encode($arrtostore);
176
    }
177
 
178
    /**
179
     * Handles rendering the element on the pdf.
180
     *
181
     * @param \pdf $pdf the pdf object
182
     * @param bool $preview true if it is a preview, false otherwise
183
     * @param \stdClass $user the user we are rendering this for
184
     */
185
    public function render($pdf, $preview, $user) {
186
        // If there is no element data, we have nothing to display.
187
        if (empty($this->get_data())) {
188
            return;
189
        }
190
 
191
        $imageinfo = json_decode($this->get_data());
192
 
193
        // If there is no file, we have nothing to display.
194
        if (empty($imageinfo->filename)) {
195
            return;
196
        }
197
 
198
        if ($file = $this->get_file()) {
199
            $location = make_request_directory() . '/target';
200
            $file->copy_content_to($location);
201
 
202
            // Check if the alpha channel is set, if it is, use it.
203
            if (isset($imageinfo->alphachannel)) {
204
                $pdf->SetAlpha($imageinfo->alphachannel);
205
            }
206
 
207
            $mimetype = $file->get_mimetype();
208
            if ($mimetype == 'image/svg+xml') {
209
                $pdf->ImageSVG($location, $this->get_posx(), $this->get_posy(), $imageinfo->width, $imageinfo->height);
210
            } else {
211
                $pdf->Image($location, $this->get_posx(), $this->get_posy(), $imageinfo->width, $imageinfo->height);
212
            }
213
 
214
            // Restore to full opacity.
215
            $pdf->SetAlpha(1);
216
        }
217
    }
218
 
219
    /**
220
     * Render the element in html.
221
     *
222
     * This function is used to render the element when we are using the
223
     * drag and drop interface to position it.
224
     *
225
     * @return string the html
226
     */
227
    public function render_html() {
228
        // If there is no element data, we have nothing to display.
229
        if (empty($this->get_data())) {
230
            return '';
231
        }
232
 
233
        $imageinfo = json_decode($this->get_data());
234
 
235
        // If there is no file, we have nothing to display.
236
        if (empty($imageinfo->filename)) {
237
            return '';
238
        }
239
 
240
        // Get the image.
241
        $fs = get_file_storage();
242
        if ($file = $fs->get_file($imageinfo->contextid, 'mod_customcert', $imageinfo->filearea, $imageinfo->itemid,
243
                $imageinfo->filepath, $imageinfo->filename)) {
244
            $url = \moodle_url::make_pluginfile_url($file->get_contextid(), 'mod_customcert', 'image', $file->get_itemid(),
245
                $file->get_filepath(), $file->get_filename());
246
            $fileimageinfo = $file->get_imageinfo();
247
            $whratio = $fileimageinfo['width'] / $fileimageinfo['height'];
248
            // The size of the images to use in the CSS style.
249
            $style = '';
250
            if ($imageinfo->width === 0 && $imageinfo->height === 0) {
251
                $style .= 'width: ' . $fileimageinfo['width'] . 'px; ';
252
                $style .= 'height: ' . $fileimageinfo['height'] . 'px';
253
            } else if ($imageinfo->width === 0) { // Then the height must be set.
254
                // We must get the width based on the height to keep the ratio.
255
                $style .= 'width: ' . ($imageinfo->height * $whratio) . 'mm; ';
256
                $style .= 'height: ' . $imageinfo->height . 'mm';
257
            } else if ($imageinfo->height === 0) { // Then the width must be set.
258
                $style .= 'width: ' . $imageinfo->width . 'mm; ';
259
                // We must get the height based on the width to keep the ratio.
260
                $style .= 'height: ' . ($imageinfo->width / $whratio) . 'mm';
261
            } else { // Must both be set.
262
                $style .= 'width: ' . $imageinfo->width . 'mm; ';
263
                $style .= 'height: ' . $imageinfo->height . 'mm';
264
            }
265
 
266
            return \html_writer::tag('img', '', ['src' => $url, 'style' => $style]);
267
        }
268
    }
269
 
270
    /**
271
     * Sets the data on the form when editing an element.
272
     *
273
     * @param \MoodleQuickForm $mform the edit_form instance
274
     */
275
    public function definition_after_data($mform) {
276
        global $COURSE, $SITE;
277
 
278
        // Set the image, width, height and alpha channel for this element.
279
        if (!empty($this->get_data())) {
280
            $imageinfo = json_decode($this->get_data());
281
            if (!empty($imageinfo->filename)) {
282
                if ($file = $this->get_file()) {
283
                    $element = $mform->getElement('fileid');
284
                    $element->setValue($file->get_id());
285
                }
286
            }
287
 
288
            if (isset($imageinfo->width) && $mform->elementExists('width')) {
289
                $element = $mform->getElement('width');
290
                $element->setValue($imageinfo->width);
291
            }
292
 
293
            if (isset($imageinfo->height) && $mform->elementExists('height')) {
294
                $element = $mform->getElement('height');
295
                $element->setValue($imageinfo->height);
296
            }
297
 
298
            if (isset($imageinfo->alphachannel) && $mform->elementExists('alphachannel')) {
299
                $element = $mform->getElement('alphachannel');
300
                $element->setValue($imageinfo->alphachannel);
301
            }
302
        }
303
 
304
        // Set the context.
305
        if ($COURSE->id == $SITE->id) {
306
            $context = \context_system::instance();
307
        } else {
308
            $context = \context_course::instance($COURSE->id);
309
        }
310
 
311
        // Editing existing instance - copy existing files into draft area.
312
        $draftitemid = file_get_submitted_draft_itemid('customcertimage');
313
        file_prepare_draft_area($draftitemid, $context->id, 'mod_customcert', 'image', 0, $this->filemanageroptions);
314
        $element = $mform->getElement('customcertimage');
315
        $element->setValue($draftitemid);
316
 
317
        parent::definition_after_data($mform);
318
    }
319
 
320
    /**
321
     * This function is responsible for handling the restoration process of the element.
322
     *
323
     * We will want to update the file's pathname hash.
324
     *
325
     * @param \restore_customcert_activity_task $restore
326
     */
327
    public function after_restore($restore) {
328
        global $DB;
329
 
330
        // Get the current data we have stored for this element.
331
        $elementinfo = json_decode($this->get_data());
332
 
333
        // Update the context.
334
        $elementinfo->contextid = \context_course::instance($restore->get_courseid())->id;
335
 
336
        // Encode again before saving.
337
        $elementinfo = json_encode($elementinfo);
338
 
339
        // Perform the update.
340
        $DB->set_field('customcert_elements', 'data', $elementinfo, ['id' => $this->get_id()]);
341
    }
342
 
343
    /**
344
     * Fetch stored file.
345
     *
346
     * @return \stored_file|bool stored_file instance if exists, false if not
347
     */
348
    public function get_file() {
349
        $imageinfo = json_decode($this->get_data());
350
 
351
        $fs = get_file_storage();
352
 
353
        return $fs->get_file($imageinfo->contextid, 'mod_customcert', $imageinfo->filearea, $imageinfo->itemid,
354
            $imageinfo->filepath, $imageinfo->filename);
355
    }
356
 
357
    /**
358
     * Return the list of possible images to use.
359
     *
360
     * @return array the list of images that can be used
361
     */
362
    public static function get_images() {
363
        global $COURSE;
364
 
365
        // Create file storage object.
366
        $fs = get_file_storage();
367
 
368
        // The array used to store the images.
369
        $arrfiles = [];
370
        // Loop through the files uploaded in the system context.
371
        if ($files = $fs->get_area_files(\context_system::instance()->id, 'mod_customcert', 'image', false, 'filename', false)) {
372
            foreach ($files as $hash => $file) {
373
                $arrfiles[$file->get_id()] = get_string('systemimage', 'customcertelement_image', $file->get_filename());
374
            }
375
        }
376
        // Loop through the files uploaded in the course context.
377
        if ($files = $fs->get_area_files(\context_course::instance($COURSE->id)->id, 'mod_customcert', 'image', false,
378
            'filename', false)) {
379
            foreach ($files as $hash => $file) {
380
                $arrfiles[$file->get_id()] = get_string('courseimage', 'customcertelement_image', $file->get_filename());
381
            }
382
        }
383
 
384
        \core_collator::asort($arrfiles);
385
        $arrfiles = ['0' => get_string('noimage', 'customcert')] + $arrfiles;
386
 
387
        return $arrfiles;
388
    }
389
 
390
    /**
391
     * This handles copying data from another element of the same type.
392
     *
393
     * @param \stdClass $data the form data
394
     * @return bool returns true if the data was copied successfully, false otherwise
395
     */
396
    public function copy_element($data) {
397
        global $COURSE, $DB, $SITE;
398
 
399
        $imagedata = json_decode($data->data);
400
 
401
        // If we are in the site context we don't have to do anything, the image is already there.
402
        if ($COURSE->id == $SITE->id) {
403
            return true;
404
        }
405
 
406
        $coursecontext = \context_course::instance($COURSE->id);
407
        $systemcontext = \context_system::instance();
408
 
409
        $fs = get_file_storage();
410
 
411
        // Check that a file has been selected.
412
        if (isset($imagedata->filearea)) {
413
            // If the course file doesn't exist, copy the system file to the course context.
414
            if (!$coursefile = $fs->get_file(
415
                $coursecontext->id,
416
                'mod_customcert',
417
                $imagedata->filearea,
418
                $imagedata->itemid,
419
                $imagedata->filepath,
420
                $imagedata->filename
421
            )) {
422
                $systemfile = $fs->get_file(
423
                    $systemcontext->id,
424
                    'mod_customcert',
425
                    $imagedata->filearea,
426
                    $imagedata->itemid,
427
                    $imagedata->filepath,
428
                    $imagedata->filename
429
                );
430
 
431
                // We want to update the context of the file if it doesn't exist in the course context.
432
                $fieldupdates = [
433
                    'contextid' => $coursecontext->id,
434
                ];
435
                $coursefile = $fs->create_file_from_storedfile($fieldupdates, $systemfile);
436
            }
437
 
438
            // Set the image to the copied file in the course.
439
            $imagedata->fileid = $coursefile->get_id();
440
            $DB->set_field('customcert_elements', 'data', $this->save_unique_data($imagedata), ['id' => $this->get_id()]);
441
        }
442
 
443
        return true;
444
    }
445
}