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 * This file contains all the class definitions of the export formats.
19 *
20 * They are implemented in php classes rather than just a simpler hash
21 * Because it provides an easy way to do subtyping using php inheritance.
22 *
23 * @package core_portfolio
24 * @copyright 2008 Penny Leach <penny@catalyst.net.nz>,
25 *                 Martin Dougiamas <http://dougiamas.com>
26 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
27 */
28
29defined('MOODLE_INTERNAL') || die();
30
31/**
32 * Base class to inherit from.
33 *
34 * Do not use this anywhere in supported_formats
35 *
36 * @package core_portfolio
37 * @category portfolio
38 * @copyright 2008 Penny Leach <penny@catalyst.net.nz>,
39 *                 Martin Dougiamas <http://dougiamas.com>
40 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
41 *
42 */
43abstract class portfolio_format {
44
45    /**
46     * Array of mimetypes this format supports
47     *
48     * @throws coding_exception
49     */
50    public static function mimetypes() {
51        throw new coding_exception('mimetypes() method needs to be overridden in each subclass of portfolio_format');
52    }
53
54    /**
55     * For multipart formats, eg html with attachments,
56     * we need to have a directory to place associated files from
57     * inside the zip file. This is the name of that directory
58     *
59     * @throws coding_exception
60     */
61    public static function get_file_directory() {
62        throw new coding_exception('get_file_directory() method needs to be overridden in each subclass of portfolio_format');
63    }
64
65    /**
66     * Given a file, return a snippet of markup in whatever format
67     * to link to that file.
68     * Usually involves the path given by get_file_directory.
69     * This is not supported in subclasses of portfolio_format_file
70     * since they're all just single files.
71     * @see get_file_directory
72     *
73     * @param stored_file $file file information object
74     * @param array $options array of options to pass. can contain:
75     *              attributes => hash of existing html attributes (eg title, height, width, etc)
76     *
77     * @throws coding_exception
78     */
79    public static function file_output($file, $options=null) {
80        throw new coding_exception('file_output() method needs to be overridden in each subclass of portfolio_format');
81    }
82
83    /**
84     * Create portfolio tag
85     *
86     * @param stored_file $file file information object
87     * @param string $path file path
88     * @param array $attributes portfolio attributes
89     * @return string
90     */
91    public static function make_tag($file, $path, $attributes) {
92        $srcattr = 'href';
93        $tag     = 'a';
94        $content = $file->get_filename();
95        if (in_array($file->get_mimetype(), portfolio_format_image::mimetypes())) {
96            $srcattr = 'src';
97            $tag     = 'img';
98            $content = '';
99        }
100
101        $attributes[$srcattr] = $path; // this will override anything we might have been passed (which is good)
102        $dom = new DomDocument();
103        $elem = null;
104        if ($content) {
105            $elem = $dom->createElement($tag, $content);
106        } else {
107            $elem = $dom->createElement($tag);
108        }
109
110        foreach ($attributes as $key => $value) {
111            $elem->setAttribute($key, $value);
112        }
113        $dom->appendChild($elem);
114        return $dom->saveXML($elem);
115    }
116
117    /**
118     * Whether this format conflicts with the given format.
119     * This is used for the case where an export location
120     * "generally" supports something like FORMAT_PLAINHTML
121     * but then in a specific export case, must add attachments,
122     * which means that FORMAT_RICHHTML is supported in that case,
123     * which implies removing support for FORMAT_PLAINHTML.
124     * Note that conflicts don't have to be bi-directional
125     * (eg FORMAT_PLAINHTML conflicts with FORMAT_RICHHTML
126     * but not the other way around) and things within the class hierarchy
127     * are resolved automatically anyway.
128     * This is really just between subclasses of format_rich
129     * and subclasses of format_file.
130     *
131     * @param string $format one of the FORMAT_XX constants
132     * @return bool
133     */
134    public static function conflicts($format) {
135        return false;
136    }
137}
138
139/**
140 * The most basic type - pretty much everything is a subtype
141 *
142 * @package core_portfolio
143 * @category portfolio
144 * @copyright 2009 Penny Leach <penny@catalyst.net.nz>, Martin Dougiamas
145 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
146 */
147class portfolio_format_file extends portfolio_format {
148
149    /**
150     * Array of mimetypes this format supports
151     *
152     * @return array
153     */
154    public static function mimetypes() {
155        return array();
156    }
157
158    /**
159     * For multipart formats, eg html with attachments,
160     * we need to have a directory to place associated files from
161     * inside the zip file. This is the name of that directory
162     *
163     * @return bool
164     */
165    public static function get_file_directory() {
166        return false;
167    }
168
169    /**
170     * Given a file, return a snippet of markup in whatever format
171     * to link to that file.
172     * Usually involves the path given by get_file_directory.
173     * This is not supported in subclasses of portfolio_format_file
174     * since they're all just single files.
175     * @see get_file_directory
176     *
177     * @param stored_file $file informations object
178     * @param array $options array of options to pass. can contain:
179     *              attributes => hash of existing html attributes (eg title, height, width, etc)
180     */
181    public static function file_output($file, $options=null) {
182        throw new portfolio_exception('fileoutputnotsupported', 'portfolio');
183    }
184}
185
186/**
187 * Image format, subtype of file.
188 *
189 * @package core_portfolio
190 * @category portfolio
191 * @copyright 2009 Penny Leach
192 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
193 */
194class portfolio_format_image extends portfolio_format_file {
195    /**
196     * Return all mimetypes that use image.gif (eg all images)
197     *
198     * @return string
199     */
200    public static function mimetypes() {
201        return file_get_typegroup('type', 'image');
202    }
203
204    /**
205     * Whether this format conflicts with the given format.
206     * This is used for the case where an export location
207     * "generally" supports something like FORMAT_PLAINHTML
208     * but then in a specific export case, must add attachments,
209     * which means that FORMAT_RICHHTML is supported in that case,
210     * which implies removing support for FORMAT_PLAINHTML.
211     * Note that conflicts don't have to be bi-directional
212     * (eg FORMAT_PLAINHTML conflicts with FORMAT_RICHHTML
213     * but not the other way around) and things within the class hierarchy
214     * are resolved automatically anyway.
215     * This is really just between subclasses of format_rich
216     * and subclasses of format_file.
217     *
218     * @param string $format one of the FORMAT_XX constants
219     * @return bool
220     */
221    public static function conflicts($format) {
222        return ($format == PORTFOLIO_FORMAT_RICHHTML
223            || $format == PORTFOLIO_FORMAT_PLAINHTML);
224    }
225}
226
227/**
228 * HTML format
229 *
230 * Could be used for an external cms or something in case we want to be really specific.
231 *
232 * @package core_portfolio
233 * @category portfolio
234 * @copyright 2008 Penny Leach
235 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
236 */
237class portfolio_format_plainhtml extends portfolio_format_file {
238
239    /**
240     * Return html mimetype
241     *
242     * @return array
243     */
244    public static function mimetypes() {
245        return array('text/html');
246    }
247
248    /**
249     * Whether this format conflicts with the given format.
250     * This is used for the case where an export location
251     * "generally" supports something like FORMAT_PLAINHTML
252     * but then in a specific export case, must add attachments,
253     * which means that FORMAT_RICHHTML is supported in that case,
254     * which implies removing support for FORMAT_PLAINHTML.
255     * Note that conflicts don't have to be bi-directional
256     * (eg FORMAT_PLAINHTML conflicts with FORMAT_RICHHTML
257     * but not the other way around) and things within the class hierarchy
258     * are resolved automatically anyway.
259     * This is really just between subclasses of format_rich
260     * and subclasses of format_file.
261     *
262     * @param string $format one of the FORMAT_XX constants
263     * @return bool
264     */
265    public static function conflicts($format) {
266        return ($format == PORTFOLIO_FORMAT_RICHHTML
267            || $format == PORTFOLIO_FORMAT_FILE);
268    }
269}
270
271/**
272 * Video format
273 *
274 * For portfolio plugins that support videos specifically
275 *
276 * @package core_portfolio
277 * @category portfolio
278 * @copyright 2008 Penny Leach
279 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
280 */
281class portfolio_format_video extends portfolio_format_file {
282
283     /**
284      * Return video mimetypes
285      *
286      * @return array
287      */
288    public static function mimetypes() {
289        return file_get_typegroup('type', 'video');
290    }
291}
292
293/**
294 * Class for plain text format.
295 *
296 * Not sure why we would need this yet,
297 * but since resource module wants to export it... we can
298 *
299 * @package core_portfolio
300 * @category portfolio
301 * @copyright 2008 Penny Leach
302 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
303 */
304class portfolio_format_text extends portfolio_format_file {
305
306    /**
307     * Return plain text mimetypes
308     *
309     * @return array
310     */
311    public static function mimetypes() {
312        return array('text/plain');
313    }
314
315    /**
316     * Whether this format conflicts with the given format.
317     * This is used for the case where an export location
318     * "generally" supports something like FORMAT_PLAINHTML
319     * but then in a specific export case, must add attachments,
320     * which means that FORMAT_RICHHTML is supported in that case,
321     * which implies removing support for FORMAT_PLAINHTML.
322     * Note that conflicts don't have to be bi-directional
323     * (eg FORMAT_PLAINHTML conflicts with FORMAT_RICHHTML
324     * but not the other way around) and things within the class hierarchy
325     * are resolved automatically anyway.
326     * This is really just between subclasses of format_rich
327     * and subclasses of format_file.
328     *
329     * @param string $format one of the FORMAT_XX constants
330     * @return bool
331     */
332    public static function conflicts($format ) {
333        return ($format == PORTFOLIO_FORMAT_PLAINHTML
334            || $format == PORTFOLIO_FORMAT_RICHHTML);
335    }
336}
337
338/**
339 * Base class for rich formats.
340 *
341 * These are multipart - eg things with attachments
342 *
343 * @package core_portfolio
344 * @category portfolio
345 * @copyright 2009 Penny Leach
346 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
347 */
348abstract class portfolio_format_rich extends portfolio_format {
349
350    /**
351     * Return rich text mimetypes
352     *
353     * @return array
354     */
355    public static function mimetypes() {
356        return array();
357    }
358
359}
360
361/**
362 * Richhtml - html with attachments.
363 *
364 * The most commonly used rich format
365 * eg inline images
366 *
367 * @package core_portfolio
368 * @category portfolio
369 * @copyright 2009 Penny Leach
370 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
371 */
372class portfolio_format_richhtml extends portfolio_format_rich {
373
374    /**
375     * For multipart formats, eg html with attachments,
376     * we need to have a directory to place associated files from
377     * inside the zip file. this is the name of that directory
378     *
379     * @return string
380     */
381    public static function get_file_directory() {
382        return 'site_files/';
383    }
384
385    /**
386     * Given a file, return a snippet of markup in whatever format
387     * to link to that file.
388     * Usually involves the path given by get_file_directory.
389     * This is not supported in subclasses of portfolio_format_file
390     * since they're all just single files.
391     * @see get_file_directory
392     *
393     * @param stored_file $file information for existing file
394     * @param array $options array of options to pass. can contain:
395     *              attributes => hash of existing html attributes (eg title, height, width, etc)
396     * @return string
397     */
398    public static function file_output($file, $options=null) {
399        $path = self::get_file_directory() . $file->get_filename();
400        $attributes = array();
401        if (!empty($options['attributes']) && is_array($options['attributes'])) {
402            $attributes = $options['attributes'];
403        }
404        return self::make_tag($file, $path, $attributes);
405    }
406
407    /**
408     * Whether this format conflicts with the given format.
409     * This is used for the case where an export location
410     * "generally" supports something like FORMAT_PLAINHTML
411     * but then in a specific export case, must add attachments,
412     * which means that FORMAT_RICHHTML is supported in that case,
413     * which implies removing support for FORMAT_PLAINHTML.
414     * Note that conflicts don't have to be bi-directional
415     * (eg FORMAT_PLAINHTML conflicts with FORMAT_RICHHTML
416     * but not the other way around) and things within the class hierarchy
417     * are resolved automatically anyway.
418     * This is really just between subclasses of format_rich
419     * and subclasses of format_file.
420     *
421     * @todo MDL-31305 - revisit the conflict with file, since we zip here
422     * @param string $format one of the FORMAT_XX constants
423     * @return bool
424     */
425    public static function conflicts($format) { // TODO revisit the conflict with file, since we zip here
426        return ($format == PORTFOLIO_FORMAT_PLAINHTML || $format == PORTFOLIO_FORMAT_FILE);
427    }
428
429}
430
431/**
432 * Class used for leap2a format
433 *
434 * @package core_portfolio
435 * @category portfolio
436 * @copyright 2009 Penny Leach
437 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
438 */
439class portfolio_format_leap2a extends portfolio_format_rich {
440
441    /**
442     * For multipart formats, eg html with attachments,
443     * we need to have a directory to place associated files from
444     * inside the zip file. this is the name of that directory
445     *
446     * @return string
447     */
448    public static function get_file_directory() {
449        return 'files/';
450    }
451
452    /**
453     * Return the file prefix
454     *
455     * @return string
456     */
457    public static function file_id_prefix() {
458        return 'storedfile';
459    }
460
461    /**
462     * Return the link to a file
463     *
464     * @param stored_file $file information for existing file
465     * @param array $options array of options to pass. can contain:
466     *              attributes => hash of existing html attributes (eg title, height, width, etc)
467     * @return string
468     */
469    public static function file_output($file, $options=null) {
470        $id = '';
471        if (!is_array($options)) {
472            $options = array();
473        }
474        if (!array_key_exists('entry', $options)) {
475            $options['entry'] = true;
476        }
477        if (!empty($options['entry'])) {
478            $path = 'portfolio:' . self::file_id_prefix() . $file->get_id();
479        } else {
480            $path = self::get_file_directory() . $file->get_filename();
481        }
482        $attributes = array();
483        if (!empty($options['attributes']) && is_array($options['attributes'])) {
484            $attributes = $options['attributes'];
485        }
486        $attributes['rel']    = 'enclosure';
487        return self::make_tag($file, $path, $attributes);
488    }
489
490    /**
491     * Generate portfolio_format_leap2a
492     *
493     * @param stdclass $user user information object
494     * @return portfolio_format_leap2a_writer
495     */
496    public static function leap2a_writer(stdclass $user=null) {
497        global $CFG;
498        if (empty($user)) {
499            global $USER;
500            $user = $USER;
501        }
502        require_once($CFG->libdir . '/portfolio/formats/leap2a/lib.php');
503        return new portfolio_format_leap2a_writer($user);
504    }
505
506    /**
507     * Return the manifest name
508     *
509     * @return string
510     */
511    public static function manifest_name() {
512        return 'leap2a.xml';
513    }
514}
515
516
517// later.... a moodle plugin might support this.
518// it's commented out in portfolio_supported_formats so cannot currently be used.
519//class portfolio_format_mbkp extends portfolio_format_rich {}
520
521/**
522 * 'PDF format', subtype of file.
523 *
524 * For portfolio plugins that support PDFs specifically.
525 *
526 * @package core_portfolio
527 * @category portfolio
528 * @copyright 2009 Dan Poltawski
529 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
530 */
531class portfolio_format_pdf extends portfolio_format_file {
532
533    /**
534     * Return pdf mimetypes
535     *
536     * @return array
537     */
538    public static function mimetypes() {
539        return array('application/pdf');
540    }
541}
542
543/**
544 * 'Document format', subtype of file.
545 *
546 * For portfolio plugins that support documents specifically.
547 *
548 * @package core_portfolio
549 * @category portfolio
550 * @copyright 2009 Dan Poltawski
551 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
552 */
553class portfolio_format_document extends portfolio_format_file {
554
555    /**
556     * Return documents mimetypes
557     *
558     * @return array of documents mimetypes
559     */
560    public static function mimetypes() {
561        return file_get_typegroup('type', 'document');
562    }
563}
564
565/**
566 * 'Spreadsheet format', subtype of file.
567 *
568 * For portfolio plugins that support spreadsheets specifically.
569 *
570 * @package core_portfolio
571 * @category portfolio
572 * @copyright 2009 Dan Poltawski
573 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
574 */
575class portfolio_format_spreadsheet extends portfolio_format_file {
576
577    /**
578     * Return spreadsheet spreadsheet mimetypes
579     *
580     * @return array of documents mimetypes
581     */
582    public static function mimetypes() {
583        return file_get_typegroup('type', 'spreadsheet');
584    }
585}
586
587/**
588 * 'Presentation format', subtype of file.
589 *
590 * For portfolio plugins that support presentation specifically.
591 *
592 * @package core_portfolio
593 * @category portfolio
594 * @copyright 2009 Dan Poltawski
595 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
596 */
597class portfolio_format_presentation extends portfolio_format_file {
598
599    /**
600     * Return presentation documents mimetypes
601     *
602     * @return array presentation document mimetypes
603     */
604    public static function mimetypes() {
605        return file_get_typegroup('type', 'presentation');
606    }
607}
608