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.
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.

/**
 * This file contains all the class definitions of the export formats.
 *
 * They are implemented in php classes rather than just a simpler hash
 * Because it provides an easy way to do subtyping using php inheritance.
 *
 * @package core_portfolio
 * @copyright 2008 Penny Leach <penny@catalyst.net.nz>,
 *                 Martin Dougiamas <http://dougiamas.com>
 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 */

defined('MOODLE_INTERNAL') || die();

/**
 * Base class to inherit from.
 *
 * Do not use this anywhere in supported_formats
 *
 * @package core_portfolio
 * @category portfolio
 * @copyright 2008 Penny Leach <penny@catalyst.net.nz>,
 *                 Martin Dougiamas <http://dougiamas.com>
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 *
 */
abstract class portfolio_format {

    /**
     * Array of mimetypes this format supports
     *
     * @throws coding_exception
     */
    public static function mimetypes() {
        throw new coding_exception('mimetypes() method needs to be overridden in each subclass of portfolio_format');
    }

    /**
     * For multipart formats, eg html with attachments,
     * we need to have a directory to place associated files from
     * inside the zip file. This is the name of that directory
     *
     * @throws coding_exception
     */
    public static function get_file_directory() {
        throw new coding_exception('get_file_directory() method needs to be overridden in each subclass of portfolio_format');
    }

    /**
     * Given a file, return a snippet of markup in whatever format
     * to link to that file.
     * Usually involves the path given by get_file_directory.
     * This is not supported in subclasses of portfolio_format_file
     * since they're all just single files.
     * @see get_file_directory
     *
     * @param stored_file $file file information object
     * @param array $options array of options to pass. can contain:
     *              attributes => hash of existing html attributes (eg title, height, width, etc)
     *
     * @throws coding_exception
     */
    public static function file_output($file, $options=null) {
        throw new coding_exception('file_output() method needs to be overridden in each subclass of portfolio_format');
    }

    /**
     * Create portfolio tag
     *
     * @param stored_file $file file information object
     * @param string $path file path
     * @param array $attributes portfolio attributes
     * @return string
     */
    public static function make_tag($file, $path, $attributes) {
        $srcattr = 'href';
        $tag     = 'a';
        $content = $file->get_filename();
        if (in_array($file->get_mimetype(), portfolio_format_image::mimetypes())) {
            $srcattr = 'src';
            $tag     = 'img';
            $content = '';
        }

        $attributes[$srcattr] = $path; // this will override anything we might have been passed (which is good)
        $dom = new DomDocument();
        $elem = null;
        if ($content) {
            $elem = $dom->createElement($tag, $content);
        } else {
            $elem = $dom->createElement($tag);
        }

        foreach ($attributes as $key => $value) {
            $elem->setAttribute($key, $value);
        }
        $dom->appendChild($elem);
        return $dom->saveXML($elem);
    }

    /**
     * Whether this format conflicts with the given format.
     * This is used for the case where an export location
     * "generally" supports something like FORMAT_PLAINHTML
     * but then in a specific export case, must add attachments,
     * which means that FORMAT_RICHHTML is supported in that case,
     * which implies removing support for FORMAT_PLAINHTML.
     * Note that conflicts don't have to be bi-directional
     * (eg FORMAT_PLAINHTML conflicts with FORMAT_RICHHTML
     * but not the other way around) and things within the class hierarchy
     * are resolved automatically anyway.
     * This is really just between subclasses of format_rich
     * and subclasses of format_file.
     *
     * @param string $format one of the FORMAT_XX constants
     * @return bool
     */
    public static function conflicts($format) {
        return false;
    }
}

/**
 * The most basic type - pretty much everything is a subtype
 *
 * @package core_portfolio
 * @category portfolio
 * @copyright 2009 Penny Leach <penny@catalyst.net.nz>, Martin Dougiamas
 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 */
class portfolio_format_file extends portfolio_format {

    /**
     * Array of mimetypes this format supports
     *
     * @return array
     */
    public static function mimetypes() {
        return array();
    }

    /**
     * For multipart formats, eg html with attachments,
     * we need to have a directory to place associated files from
     * inside the zip file. This is the name of that directory
     *
     * @return bool
     */
    public static function get_file_directory() {
        return false;
    }

    /**
     * Given a file, return a snippet of markup in whatever format
     * to link to that file.
     * Usually involves the path given by get_file_directory.
     * This is not supported in subclasses of portfolio_format_file
     * since they're all just single files.
     * @see get_file_directory
     *
     * @param stored_file $file informations object
     * @param array $options array of options to pass. can contain:
     *              attributes => hash of existing html attributes (eg title, height, width, etc)
     */
    public static function file_output($file, $options=null) {
        throw new portfolio_exception('fileoutputnotsupported', 'portfolio');
    }
}

/**
 * Image format, subtype of file.
 *
 * @package core_portfolio
 * @category portfolio
 * @copyright 2009 Penny Leach
 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 */
class portfolio_format_image extends portfolio_format_file {
    /**
     * Return all mimetypes that use image.gif (eg all images)
     *
< * @return string
> * @return array
*/ public static function mimetypes() { return file_get_typegroup('type', 'image'); } /** * Whether this format conflicts with the given format. * This is used for the case where an export location * "generally" supports something like FORMAT_PLAINHTML * but then in a specific export case, must add attachments, * which means that FORMAT_RICHHTML is supported in that case, * which implies removing support for FORMAT_PLAINHTML. * Note that conflicts don't have to be bi-directional * (eg FORMAT_PLAINHTML conflicts with FORMAT_RICHHTML * but not the other way around) and things within the class hierarchy * are resolved automatically anyway. * This is really just between subclasses of format_rich * and subclasses of format_file. * * @param string $format one of the FORMAT_XX constants * @return bool */ public static function conflicts($format) { return ($format == PORTFOLIO_FORMAT_RICHHTML || $format == PORTFOLIO_FORMAT_PLAINHTML); } } /** * HTML format * * Could be used for an external cms or something in case we want to be really specific. * * @package core_portfolio * @category portfolio * @copyright 2008 Penny Leach * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class portfolio_format_plainhtml extends portfolio_format_file { /** * Return html mimetype * * @return array */ public static function mimetypes() { return array('text/html'); } /** * Whether this format conflicts with the given format. * This is used for the case where an export location * "generally" supports something like FORMAT_PLAINHTML * but then in a specific export case, must add attachments, * which means that FORMAT_RICHHTML is supported in that case, * which implies removing support for FORMAT_PLAINHTML. * Note that conflicts don't have to be bi-directional * (eg FORMAT_PLAINHTML conflicts with FORMAT_RICHHTML * but not the other way around) and things within the class hierarchy * are resolved automatically anyway. * This is really just between subclasses of format_rich * and subclasses of format_file. * * @param string $format one of the FORMAT_XX constants * @return bool */ public static function conflicts($format) { return ($format == PORTFOLIO_FORMAT_RICHHTML || $format == PORTFOLIO_FORMAT_FILE); } } /** * Video format * * For portfolio plugins that support videos specifically * * @package core_portfolio * @category portfolio * @copyright 2008 Penny Leach * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class portfolio_format_video extends portfolio_format_file { /** * Return video mimetypes * * @return array */ public static function mimetypes() { return file_get_typegroup('type', 'video'); } } /** * Class for plain text format. * * Not sure why we would need this yet, * but since resource module wants to export it... we can * * @package core_portfolio * @category portfolio * @copyright 2008 Penny Leach * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class portfolio_format_text extends portfolio_format_file { /** * Return plain text mimetypes * * @return array */ public static function mimetypes() { return array('text/plain'); } /** * Whether this format conflicts with the given format. * This is used for the case where an export location * "generally" supports something like FORMAT_PLAINHTML * but then in a specific export case, must add attachments, * which means that FORMAT_RICHHTML is supported in that case, * which implies removing support for FORMAT_PLAINHTML. * Note that conflicts don't have to be bi-directional * (eg FORMAT_PLAINHTML conflicts with FORMAT_RICHHTML * but not the other way around) and things within the class hierarchy * are resolved automatically anyway. * This is really just between subclasses of format_rich * and subclasses of format_file. * * @param string $format one of the FORMAT_XX constants * @return bool */ public static function conflicts($format ) { return ($format == PORTFOLIO_FORMAT_PLAINHTML || $format == PORTFOLIO_FORMAT_RICHHTML); } } /** * Base class for rich formats. * * These are multipart - eg things with attachments * * @package core_portfolio * @category portfolio * @copyright 2009 Penny Leach * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ abstract class portfolio_format_rich extends portfolio_format { /** * Return rich text mimetypes * * @return array */ public static function mimetypes() { return array(); } } /** * Richhtml - html with attachments. * * The most commonly used rich format * eg inline images * * @package core_portfolio * @category portfolio * @copyright 2009 Penny Leach * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class portfolio_format_richhtml extends portfolio_format_rich { /** * For multipart formats, eg html with attachments, * we need to have a directory to place associated files from * inside the zip file. this is the name of that directory * * @return string */ public static function get_file_directory() { return 'site_files/'; } /** * Given a file, return a snippet of markup in whatever format * to link to that file. * Usually involves the path given by get_file_directory. * This is not supported in subclasses of portfolio_format_file * since they're all just single files. * @see get_file_directory * * @param stored_file $file information for existing file * @param array $options array of options to pass. can contain: * attributes => hash of existing html attributes (eg title, height, width, etc) * @return string */ public static function file_output($file, $options=null) { $path = self::get_file_directory() . $file->get_filename(); $attributes = array(); if (!empty($options['attributes']) && is_array($options['attributes'])) { $attributes = $options['attributes']; } return self::make_tag($file, $path, $attributes); } /** * Whether this format conflicts with the given format. * This is used for the case where an export location * "generally" supports something like FORMAT_PLAINHTML * but then in a specific export case, must add attachments, * which means that FORMAT_RICHHTML is supported in that case, * which implies removing support for FORMAT_PLAINHTML. * Note that conflicts don't have to be bi-directional * (eg FORMAT_PLAINHTML conflicts with FORMAT_RICHHTML * but not the other way around) and things within the class hierarchy * are resolved automatically anyway. * This is really just between subclasses of format_rich * and subclasses of format_file. * * @todo MDL-31305 - revisit the conflict with file, since we zip here * @param string $format one of the FORMAT_XX constants * @return bool */ public static function conflicts($format) { // TODO revisit the conflict with file, since we zip here return ($format == PORTFOLIO_FORMAT_PLAINHTML || $format == PORTFOLIO_FORMAT_FILE); } } /** * Class used for leap2a format * * @package core_portfolio * @category portfolio * @copyright 2009 Penny Leach * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class portfolio_format_leap2a extends portfolio_format_rich { /** * For multipart formats, eg html with attachments, * we need to have a directory to place associated files from * inside the zip file. this is the name of that directory * * @return string */ public static function get_file_directory() { return 'files/'; } /** * Return the file prefix * * @return string */ public static function file_id_prefix() { return 'storedfile'; } /** * Return the link to a file * * @param stored_file $file information for existing file * @param array $options array of options to pass. can contain: * attributes => hash of existing html attributes (eg title, height, width, etc) * @return string */ public static function file_output($file, $options=null) { $id = ''; if (!is_array($options)) { $options = array(); } if (!array_key_exists('entry', $options)) { $options['entry'] = true; } if (!empty($options['entry'])) { $path = 'portfolio:' . self::file_id_prefix() . $file->get_id(); } else { $path = self::get_file_directory() . $file->get_filename(); } $attributes = array(); if (!empty($options['attributes']) && is_array($options['attributes'])) { $attributes = $options['attributes']; } $attributes['rel'] = 'enclosure'; return self::make_tag($file, $path, $attributes); } /** * Generate portfolio_format_leap2a * * @param stdclass $user user information object * @return portfolio_format_leap2a_writer */ public static function leap2a_writer(stdclass $user=null) { global $CFG; if (empty($user)) { global $USER; $user = $USER; } require_once($CFG->libdir . '/portfolio/formats/leap2a/lib.php'); return new portfolio_format_leap2a_writer($user); } /** * Return the manifest name * * @return string */ public static function manifest_name() { return 'leap2a.xml'; } } // later.... a moodle plugin might support this. // it's commented out in portfolio_supported_formats so cannot currently be used. //class portfolio_format_mbkp extends portfolio_format_rich {} /** * 'PDF format', subtype of file. * * For portfolio plugins that support PDFs specifically. * * @package core_portfolio * @category portfolio * @copyright 2009 Dan Poltawski * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class portfolio_format_pdf extends portfolio_format_file { /** * Return pdf mimetypes * * @return array */ public static function mimetypes() { return array('application/pdf'); } } /** * 'Document format', subtype of file. * * For portfolio plugins that support documents specifically. * * @package core_portfolio * @category portfolio * @copyright 2009 Dan Poltawski * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class portfolio_format_document extends portfolio_format_file { /** * Return documents mimetypes * * @return array of documents mimetypes */ public static function mimetypes() { return file_get_typegroup('type', 'document'); } } /** * 'Spreadsheet format', subtype of file. * * For portfolio plugins that support spreadsheets specifically. * * @package core_portfolio * @category portfolio * @copyright 2009 Dan Poltawski * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class portfolio_format_spreadsheet extends portfolio_format_file { /** * Return spreadsheet spreadsheet mimetypes * * @return array of documents mimetypes */ public static function mimetypes() { return file_get_typegroup('type', 'spreadsheet'); } } /** * 'Presentation format', subtype of file. * * For portfolio plugins that support presentation specifically. * * @package core_portfolio * @category portfolio * @copyright 2009 Dan Poltawski * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class portfolio_format_presentation extends portfolio_format_file { /** * Return presentation documents mimetypes * * @return array presentation document mimetypes */ public static function mimetypes() { return file_get_typegroup('type', 'presentation'); } }