See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 and 401] [Versions 401 and 403]
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 * Class to manage the custom filetypes list that is stored in a config variable. 19 * 20 * @package core 21 * @copyright 2014 The Open University 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 defined('MOODLE_INTERNAL') || die(); 26 27 require_once($CFG->libdir . '/filelib.php'); 28 29 /** 30 * Class to manage the custom filetypes list that is stored in a config variable. 31 * 32 * @copyright 2014 The Open University 33 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 34 */ 35 abstract class core_filetypes { 36 /** @var array Cached MIME types for current request */ 37 protected static $cachedtypes; 38 39 /** 40 * Gets default MIME types that are included as standard. 41 * 42 * Note: Use the function get_mimetypes_array to access this data including 43 * any customisations the user might have made. 44 * 45 * @return array Default (pre-installed) MIME type information 46 */ 47 protected static function get_default_types() { 48 return array( 49 'xxx' => array('type' => 'document/unknown', 'icon' => 'unknown'), 50 '3gp' => array('type' => 'video/quicktime', 'icon' => 'quicktime', 'groups' => array('video'), 'string' => 'video'), 51 '7z' => array('type' => 'application/x-7z-compressed', 'icon' => 'archive', 52 'groups' => array('archive'), 'string' => 'archive'), 53 'aac' => array('type' => 'audio/aac', 'icon' => 'audio', 'groups' => array('audio', 'html_audio', 'web_audio'), 54 'string' => 'audio'), 55 'accdb' => array('type' => 'application/msaccess', 'icon' => 'base'), 56 'ai' => array('type' => 'application/postscript', 'icon' => 'eps', 'groups' => array('image'), 'string' => 'image'), 57 'aif' => array('type' => 'audio/x-aiff', 'icon' => 'audio', 'groups' => array('audio'), 'string' => 'audio'), 58 'aiff' => array('type' => 'audio/x-aiff', 'icon' => 'audio', 'groups' => array('audio'), 'string' => 'audio'), 59 'aifc' => array('type' => 'audio/x-aiff', 'icon' => 'audio', 'groups' => array('audio'), 'string' => 'audio'), 60 'applescript' => array('type' => 'text/plain', 'icon' => 'text'), 61 'asc' => array('type' => 'text/plain', 'icon' => 'sourcecode'), 62 'asm' => array('type' => 'text/plain', 'icon' => 'sourcecode'), 63 'au' => array('type' => 'audio/au', 'icon' => 'audio', 'groups' => array('audio'), 'string' => 'audio'), 64 'avi' => array('type' => 'video/x-ms-wm', 'icon' => 'avi', 65 'groups' => array('video', 'web_video'), 'string' => 'video'), 66 'bmp' => array('type' => 'image/bmp', 'icon' => 'bmp', 'groups' => array('image'), 'string' => 'image'), 67 'c' => array('type' => 'text/plain', 'icon' => 'sourcecode'), 68 'cct' => array('type' => 'shockwave/director', 'icon' => 'flash'), 69 'cpp' => array('type' => 'text/plain', 'icon' => 'sourcecode'), 70 'cs' => array('type' => 'application/x-csh', 'icon' => 'sourcecode'), 71 'css' => array('type' => 'text/css', 'icon' => 'text', 'groups' => array('web_file')), 72 'csv' => array('type' => 'text/csv', 'icon' => 'spreadsheet', 'groups' => array('spreadsheet')), 73 'dv' => array('type' => 'video/x-dv', 'icon' => 'quicktime', 'groups' => array('video'), 'string' => 'video'), 74 'dmg' => array('type' => 'application/octet-stream', 'icon' => 'unknown'), 75 76 'doc' => array('type' => 'application/msword', 'icon' => 'document', 'groups' => array('document')), 77 'bdoc' => array('type' => 'application/x-digidoc', 'icon' => 'document', 'groups' => array('archive')), 78 'cdoc' => array('type' => 'application/x-digidoc', 'icon' => 'document', 'groups' => array('archive')), 79 'ddoc' => array('type' => 'application/x-digidoc', 'icon' => 'document', 'groups' => array('archive')), 80 'docx' => array('type' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 81 'icon' => 'document', 'groups' => array('document')), 82 'docm' => array('type' => 'application/vnd.ms-word.document.macroEnabled.12', 'icon' => 'document'), 83 'dotx' => array('type' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template', 84 'icon' => 'document'), 85 'dotm' => array('type' => 'application/vnd.ms-word.template.macroEnabled.12', 'icon' => 'document'), 86 87 'dcr' => array('type' => 'application/x-director', 'icon' => 'flash'), 88 'dif' => array('type' => 'video/x-dv', 'icon' => 'quicktime', 'groups' => array('video'), 'string' => 'video'), 89 'dir' => array('type' => 'application/x-director', 'icon' => 'flash'), 90 'dxr' => array('type' => 'application/x-director', 'icon' => 'flash'), 91 'eps' => array('type' => 'application/postscript', 'icon' => 'eps'), 92 'epub' => array('type' => 'application/epub+zip', 'icon' => 'epub', 'groups' => array('document')), 93 'fdf' => array('type' => 'application/vnd.fdf', 'icon' => 'pdf'), 94 'flac' => array('type' => 'audio/flac', 'icon' => 'audio', 'groups' => array('audio', 'html_audio', 'web_audio'), 95 'string' => 'audio'), 96 'flv' => array('type' => 'video/x-flv', 'icon' => 'flash', 97 'groups' => array('video', 'web_video'), 'string' => 'video'), 98 'f4v' => array('type' => 'video/mp4', 'icon' => 'flash', 'groups' => array('video', 'web_video'), 'string' => 'video'), 99 'fmp4' => array('type' => 'video/mp4', 'icon' => 'mpeg', 'groups' => array('html_video', 'video', 'web_video'), 100 'string' => 'video'), 101 'gallery' => array('type' => 'application/x-smarttech-notebook', 'icon' => 'archive'), 102 'galleryitem' => array('type' => 'application/x-smarttech-notebook', 'icon' => 'archive'), 103 'gallerycollection' => array('type' => 'application/x-smarttech-notebook', 'icon' => 'archive'), 104 'gdraw' => array('type' => 'application/vnd.google-apps.drawing', 'icon' => 'image', 'groups' => array('image')), 105 'gdoc' => array('type' => 'application/vnd.google-apps.document', 'icon' => 'document', 'groups' => array('document')), 106 'gsheet' => array('type' => 'application/vnd.google-apps.spreadsheet', 'icon' => 'spreadsheet', 107 'groups' => array('spreadsheet')), 108 'gslides' => array('type' => 'application/vnd.google-apps.presentation', 'icon' => 'powerpoint', 109 'groups' => array('presentation')), 110 'gif' => array('type' => 'image/gif', 'icon' => 'gif', 'groups' => array('image', 'web_image', 'optimised_image'), 111 'string' => 'image'), 112 'gtar' => array('type' => 'application/x-gtar', 'icon' => 'archive', 113 'groups' => array('archive'), 'string' => 'archive'), 114 'tgz' => array('type' => 'application/g-zip', 'icon' => 'archive', 'groups' => array('archive'), 'string' => 'archive'), 115 'gz' => array('type' => 'application/g-zip', 'icon' => 'archive', 'groups' => array('archive'), 'string' => 'archive'), 116 'gzip' => array('type' => 'application/g-zip', 'icon' => 'archive', 117 'groups' => array('archive'), 'string' => 'archive'), 118 'h' => array('type' => 'text/plain', 'icon' => 'sourcecode'), 119 'h5p' => array('type' => 'application/zip.h5p', 'icon' => 'h5p', 'string' => 'archive'), 120 'hpp' => array('type' => 'text/plain', 'icon' => 'sourcecode'), 121 'hqx' => array('type' => 'application/mac-binhex40', 'icon' => 'archive', 122 'groups' => array('archive'), 'string' => 'archive'), 123 'htc' => array('type' => 'text/x-component', 'icon' => 'markup'), 124 'html' => array('type' => 'text/html', 'icon' => 'html', 'groups' => array('web_file')), 125 'xhtml' => array('type' => 'application/xhtml+xml', 'icon' => 'html', 'groups' => array('web_file')), 126 'htm' => array('type' => 'text/html', 'icon' => 'html', 'groups' => array('web_file')), 127 'ico' => array('type' => 'image/vnd.microsoft.icon', 'icon' => 'image', 128 'groups' => array('image'), 'string' => 'image'), 129 'ics' => array('type' => 'text/calendar', 'icon' => 'text'), 130 'isf' => array('type' => 'application/inspiration', 'icon' => 'isf'), 131 'ist' => array('type' => 'application/inspiration.template', 'icon' => 'isf'), 132 'java' => array('type' => 'text/plain', 'icon' => 'sourcecode'), 133 'jar' => array('type' => 'application/java-archive', 'icon' => 'archive'), 134 'jcb' => array('type' => 'text/xml', 'icon' => 'markup'), 135 'jcl' => array('type' => 'text/xml', 'icon' => 'markup'), 136 'jcw' => array('type' => 'text/xml', 'icon' => 'markup'), 137 'jmt' => array('type' => 'text/xml', 'icon' => 'markup'), 138 'jmx' => array('type' => 'text/xml', 'icon' => 'markup'), 139 'jnlp' => array('type' => 'application/x-java-jnlp-file', 'icon' => 'markup'), 140 'jpe' => array('type' => 'image/jpeg', 'icon' => 'jpeg', 'groups' => array('image', 'web_image', 'optimised_image'), 141 'string' => 'image'), 142 'jpeg' => array('type' => 'image/jpeg', 'icon' => 'jpeg', 'groups' => array('image', 'web_image', 'optimised_image'), 143 'string' => 'image'), 144 'jpg' => array('type' => 'image/jpeg', 'icon' => 'jpeg', 'groups' => array('image', 'web_image', 'optimised_image'), 145 'string' => 'image'), 146 'jqz' => array('type' => 'text/xml', 'icon' => 'markup'), 147 'js' => array('type' => 'application/x-javascript', 'icon' => 'text', 'groups' => array('web_file')), 148 'json' => array('type' => 'application/json', 'icon' => 'text'), 149 'latex' => array('type' => 'application/x-latex', 'icon' => 'text'), 150 'm' => array('type' => 'text/plain', 'icon' => 'sourcecode'), 151 'mbz' => array('type' => 'application/vnd.moodle.backup', 'icon' => 'moodle'), 152 'mdb' => array('type' => 'application/x-msaccess', 'icon' => 'base'), 153 'mht' => array('type' => 'message/rfc822', 'icon' => 'archive'), 154 'mhtml' => array('type' => 'message/rfc822', 'icon' => 'archive'), 155 'mov' => array('type' => 'video/quicktime', 'icon' => 'quicktime', 156 'groups' => array('video', 'web_video', 'html_video'), 'string' => 'video'), 157 'movie' => array('type' => 'video/x-sgi-movie', 'icon' => 'quicktime', 'groups' => array('video'), 'string' => 'video'), 158 'mw' => array('type' => 'application/maple', 'icon' => 'math'), 159 'mws' => array('type' => 'application/maple', 'icon' => 'math'), 160 'm3u' => array('type' => 'audio/x-mpegurl', 'icon' => 'mp3', 'groups' => array('audio'), 'string' => 'audio'), 161 'm3u8' => array('type' => 'application/x-mpegURL', 'icon' => 'mpeg', 'groups' => array('media_source')), 162 'mp3' => array('type' => 'audio/mp3', 'icon' => 'mp3', 'groups' => array('audio', 'html_audio', 'web_audio'), 163 'string' => 'audio'), 164 'mp4' => array('type' => 'video/mp4', 'icon' => 'mpeg', 'groups' => array('html_video', 'video', 'web_video'), 165 'string' => 'video'), 166 'm4v' => array('type' => 'video/mp4', 'icon' => 'mpeg', 'groups' => array('html_video', 'video', 'web_video'), 167 'string' => 'video'), 168 'm4a' => array('type' => 'audio/mp4', 'icon' => 'mp3', 'groups' => array('audio', 'html_audio', 'web_audio'), 169 'string' => 'audio'), 170 'mpeg' => array('type' => 'video/mpeg', 'icon' => 'mpeg', 'groups' => array('video', 'web_video'), 171 'string' => 'video'), 172 'mpd' => array('type' => 'application/dash+xml', 'icon' => 'mpeg', 'groups' => array('media_source')), 173 'mpe' => array('type' => 'video/mpeg', 'icon' => 'mpeg', 'groups' => array('video', 'web_video'), 174 'string' => 'video'), 175 'mpg' => array('type' => 'video/mpeg', 'icon' => 'mpeg', 'groups' => array('video', 'web_video'), 176 'string' => 'video'), 177 'mpr' => array('type' => 'application/vnd.moodle.profiling', 'icon' => 'moodle'), 178 179 'nbk' => array('type' => 'application/x-smarttech-notebook', 'icon' => 'archive'), 180 'notebook' => array('type' => 'application/x-smarttech-notebook', 'icon' => 'archive'), 181 182 'odt' => array('type' => 'application/vnd.oasis.opendocument.text', 'icon' => 'writer', 'groups' => array('document')), 183 'ott' => array('type' => 'application/vnd.oasis.opendocument.text-template', 184 'icon' => 'writer', 'groups' => array('document')), 185 'oth' => array('type' => 'application/vnd.oasis.opendocument.text-web', 'icon' => 'oth', 'groups' => array('document')), 186 'odm' => array('type' => 'application/vnd.oasis.opendocument.text-master', 'icon' => 'writer'), 187 'odg' => array('type' => 'application/vnd.oasis.opendocument.graphics', 'icon' => 'draw'), 188 'otg' => array('type' => 'application/vnd.oasis.opendocument.graphics-template', 'icon' => 'draw'), 189 'odp' => array('type' => 'application/vnd.oasis.opendocument.presentation', 'icon' => 'impress', 190 'groups' => array('presentation')), 191 'otp' => array('type' => 'application/vnd.oasis.opendocument.presentation-template', 'icon' => 'impress', 192 'groups' => array('presentation')), 193 'ods' => array('type' => 'application/vnd.oasis.opendocument.spreadsheet', 194 'icon' => 'calc', 'groups' => array('spreadsheet')), 195 'ots' => array('type' => 'application/vnd.oasis.opendocument.spreadsheet-template', 196 'icon' => 'calc', 'groups' => array('spreadsheet')), 197 'odc' => array('type' => 'application/vnd.oasis.opendocument.chart', 'icon' => 'chart'), 198 'odf' => array('type' => 'application/vnd.oasis.opendocument.formula', 'icon' => 'math'), 199 'odb' => array('type' => 'application/vnd.oasis.opendocument.database', 'icon' => 'base'), 200 'odi' => array('type' => 'application/vnd.oasis.opendocument.image', 'icon' => 'draw'), 201 'oga' => array('type' => 'audio/ogg', 'icon' => 'audio', 'groups' => array('audio', 'html_audio', 'web_audio'), 202 'string' => 'audio'), 203 'ogg' => array('type' => 'audio/ogg', 'icon' => 'audio', 'groups' => array('audio', 'html_audio', 'web_audio'), 204 'string' => 'audio'), 205 'ogv' => array('type' => 'video/ogg', 'icon' => 'video', 'groups' => array('html_video', 'video', 'web_video'), 206 'string' => 'video'), 207 208 'pct' => array('type' => 'image/pict', 'icon' => 'image', 'groups' => array('image'), 'string' => 'image'), 209 'pdf' => array('type' => 'application/pdf', 'icon' => 'pdf', 'groups' => array('document')), 210 'php' => array('type' => 'text/plain', 'icon' => 'sourcecode'), 211 'pic' => array('type' => 'image/pict', 'icon' => 'image', 'groups' => array('image'), 'string' => 'image'), 212 'pict' => array('type' => 'image/pict', 'icon' => 'image', 'groups' => array('image'), 'string' => 'image'), 213 'png' => array('type' => 'image/png', 'icon' => 'png', 'groups' => array('image', 'web_image', 'optimised_image'), 214 'string' => 'image'), 215 'pps' => array('type' => 'application/vnd.ms-powerpoint', 'icon' => 'powerpoint', 'groups' => array('presentation')), 216 'ppt' => array('type' => 'application/vnd.ms-powerpoint', 'icon' => 'powerpoint', 'groups' => array('presentation')), 217 'pptx' => array('type' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation', 218 'icon' => 'powerpoint', 'groups' => array('presentation')), 219 'pptm' => array('type' => 'application/vnd.ms-powerpoint.presentation.macroEnabled.12', 'icon' => 'powerpoint', 220 'groups' => array('presentation')), 221 'potx' => array('type' => 'application/vnd.openxmlformats-officedocument.presentationml.template', 222 'icon' => 'powerpoint', 'groups' => array('presentation')), 223 'potm' => array('type' => 'application/vnd.ms-powerpoint.template.macroEnabled.12', 'icon' => 'powerpoint', 224 'groups' => array('presentation')), 225 'ppam' => array('type' => 'application/vnd.ms-powerpoint.addin.macroEnabled.12', 'icon' => 'powerpoint', 226 'groups' => array('presentation')), 227 'ppsx' => array('type' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow', 228 'icon' => 'powerpoint', 'groups' => array('presentation')), 229 'ppsm' => array('type' => 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12', 'icon' => 'powerpoint', 230 'groups' => array('presentation')), 231 'ps' => array('type' => 'application/postscript', 'icon' => 'pdf'), 232 'pub' => array('type' => 'application/x-mspublisher', 'icon' => 'publisher', 'groups' => array('presentation')), 233 234 'qt' => array('type' => 'video/quicktime', 'icon' => 'quicktime', 235 'groups' => array('video', 'web_video'), 'string' => 'video'), 236 'ra' => array('type' => 'audio/x-realaudio-plugin', 'icon' => 'audio', 237 'groups' => array('audio', 'web_audio'), 'string' => 'audio'), 238 'ram' => array('type' => 'audio/x-pn-realaudio-plugin', 'icon' => 'audio', 239 'groups' => array('audio'), 'string' => 'audio'), 240 'rar' => array('type' => 'application/x-rar-compressed', 'icon' => 'archive', 241 'groups' => array('archive'), 'string' => 'archive'), 242 'rhb' => array('type' => 'text/xml', 'icon' => 'markup'), 243 'rm' => array('type' => 'audio/x-pn-realaudio-plugin', 'icon' => 'audio', 244 'groups' => array('audio'), 'string' => 'audio'), 245 'rmvb' => array('type' => 'application/vnd.rn-realmedia-vbr', 'icon' => 'video', 246 'groups' => array('video'), 'string' => 'video'), 247 'rtf' => array('type' => 'text/rtf', 'icon' => 'text', 'groups' => array('document')), 248 'rtx' => array('type' => 'text/richtext', 'icon' => 'text'), 249 'rv' => array('type' => 'audio/x-pn-realaudio-plugin', 'icon' => 'audio', 250 'groups' => array('video'), 'string' => 'video'), 251 'scss' => array('type' => 'text/x-scss', 'icon' => 'text', 'groups' => array('web_file')), 252 'sh' => array('type' => 'application/x-sh', 'icon' => 'sourcecode'), 253 'sit' => array('type' => 'application/x-stuffit', 'icon' => 'archive', 254 'groups' => array('archive'), 'string' => 'archive'), 255 'smi' => array('type' => 'application/smil', 'icon' => 'text'), 256 'smil' => array('type' => 'application/smil', 'icon' => 'text'), 257 'sqt' => array('type' => 'text/xml', 'icon' => 'markup'), 258 'svg' => array('type' => 'image/svg+xml', 'icon' => 'image', 259 'groups' => array('image', 'web_image'), 'string' => 'image'), 260 'svgz' => array('type' => 'image/svg+xml', 'icon' => 'image', 261 'groups' => array('image', 'web_image'), 'string' => 'image'), 262 'swa' => array('type' => 'application/x-director', 'icon' => 'flash'), 263 'swf' => array('type' => 'application/x-shockwave-flash', 'icon' => 'flash'), 264 'swfl' => array('type' => 'application/x-shockwave-flash', 'icon' => 'flash'), 265 266 'sxw' => array('type' => 'application/vnd.sun.xml.writer', 'icon' => 'writer'), 267 'stw' => array('type' => 'application/vnd.sun.xml.writer.template', 'icon' => 'writer'), 268 'sxc' => array('type' => 'application/vnd.sun.xml.calc', 'icon' => 'calc'), 269 'stc' => array('type' => 'application/vnd.sun.xml.calc.template', 'icon' => 'calc'), 270 'sxd' => array('type' => 'application/vnd.sun.xml.draw', 'icon' => 'draw'), 271 'std' => array('type' => 'application/vnd.sun.xml.draw.template', 'icon' => 'draw'), 272 'sxi' => array('type' => 'application/vnd.sun.xml.impress', 'icon' => 'impress', 'groups' => array('presentation')), 273 'sti' => array('type' => 'application/vnd.sun.xml.impress.template', 'icon' => 'impress', 274 'groups' => array('presentation')), 275 'sxg' => array('type' => 'application/vnd.sun.xml.writer.global', 'icon' => 'writer'), 276 'sxm' => array('type' => 'application/vnd.sun.xml.math', 'icon' => 'math'), 277 278 'tar' => array('type' => 'application/x-tar', 'icon' => 'archive', 'groups' => array('archive'), 'string' => 'archive'), 279 'tif' => array('type' => 'image/tiff', 'icon' => 'tiff', 'groups' => array('image'), 'string' => 'image'), 280 'tiff' => array('type' => 'image/tiff', 'icon' => 'tiff', 'groups' => array('image'), 'string' => 'image'), 281 'tex' => array('type' => 'application/x-tex', 'icon' => 'text'), 282 'texi' => array('type' => 'application/x-texinfo', 'icon' => 'text'), 283 'texinfo' => array('type' => 'application/x-texinfo', 'icon' => 'text'), 284 'ts' => array('type' => 'video/MP2T', 'icon' => 'mpeg', 'groups' => array('video', 'web_video'), 285 'string' => 'video'), 286 'tsv' => array('type' => 'text/tab-separated-values', 'icon' => 'text'), 287 'txt' => array('type' => 'text/plain', 'icon' => 'text', 'defaulticon' => true), 288 'vtt' => array('type' => 'text/vtt', 'icon' => 'text', 'groups' => array('html_track')), 289 'wav' => array('type' => 'audio/wav', 'icon' => 'wav', 'groups' => array('audio', 'html_audio', 'web_audio'), 290 'string' => 'audio'), 291 'webm' => array('type' => 'video/webm', 'icon' => 'video', 'groups' => array('html_video', 'video', 'web_video'), 292 'string' => 'video'), 293 'wmv' => array('type' => 'video/x-ms-wmv', 'icon' => 'wmv', 'groups' => array('video'), 'string' => 'video'), 294 'asf' => array('type' => 'video/x-ms-asf', 'icon' => 'wmv', 'groups' => array('video'), 'string' => 'video'), 295 'wma' => array('type' => 'audio/x-ms-wma', 'icon' => 'audio', 'groups' => array('audio'), 'string' => 'audio'), 296 297 'xbk' => array('type' => 'application/x-smarttech-notebook', 'icon' => 'archive'), 298 'xdp' => array('type' => 'application/vnd.adobe.xdp+xml', 'icon' => 'pdf'), 299 'xfd' => array('type' => 'application/vnd.xfdl', 'icon' => 'pdf'), 300 'xfdf' => array('type' => 'application/vnd.adobe.xfdf', 'icon' => 'pdf'), 301 302 'xls' => array('type' => 'application/vnd.ms-excel', 'icon' => 'spreadsheet', 'groups' => array('spreadsheet')), 303 'xlsx' => array('type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'icon' => 'spreadsheet', 304 'groups' => array('spreadsheet')), 305 'xlsm' => array('type' => 'application/vnd.ms-excel.sheet.macroEnabled.12', 306 'icon' => 'spreadsheet', 'groups' => array('spreadsheet')), 307 'xltx' => array('type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template', 308 'icon' => 'spreadsheet'), 309 'xltm' => array('type' => 'application/vnd.ms-excel.template.macroEnabled.12', 'icon' => 'spreadsheet'), 310 'xlsb' => array('type' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12', 'icon' => 'spreadsheet'), 311 'xlam' => array('type' => 'application/vnd.ms-excel.addin.macroEnabled.12', 'icon' => 'spreadsheet'), 312 313 'xml' => array('type' => 'application/xml', 'icon' => 'markup'), 314 'xsl' => array('type' => 'text/xml', 'icon' => 'markup'), 315 316 'yaml' => array('type' => 'application/yaml', 'icon' => 'markup'), 317 'yml' => array('type' => 'application/yaml', 'icon' => 'markup'), 318 319 'zip' => array('type' => 'application/zip', 'icon' => 'archive', 'groups' => array('archive'), 'string' => 'archive') 320 ); 321 } 322 323 /** 324 * Given a mimetype - return a valid file extension for it. 325 * 326 * @param $mimetype string 327 * @return string|bool False if the mimetype was not known, a string indicating a valid file extension otherwise. It may not 328 * be the only valid file extension - just the first one found. 329 */ 330 public static function get_file_extension($mimetype) { 331 $types = self::get_types(); 332 foreach ($types as $extension => $info) { 333 if ($info['type'] == $mimetype) { 334 return $extension; 335 } 336 } 337 return false; 338 } 339 340 /** 341 * Gets all the current types. 342 * 343 * @return array Associative array from extension to array of data about type 344 */ 345 public static function &get_types() { 346 // If it was already done in this request, use cache. 347 if (self::$cachedtypes) { 348 return self::$cachedtypes; 349 } 350 351 // Get defaults. 352 $mimetypes = self::get_default_types(); 353 354 // Get custom file types. 355 $custom = self::get_custom_types(); 356 357 // Check value is an array. 358 if (!is_array($custom)) { 359 debugging('Invalid $CFG->customfiletypes (not array)', DEBUG_DEVELOPER); 360 $custom = array(); 361 } 362 363 foreach ($custom as $customentry) { 364 // Each entry is a stdClass object similar to the array values above. 365 if (empty($customentry->extension)) { 366 debugging('Invalid $CFG->customfiletypes entry (extension field required)', 367 DEBUG_DEVELOPER); 368 continue; 369 } 370 371 // To delete a standard entry, set 'deleted' to true. 372 if (!empty($customentry->deleted)) { 373 unset($mimetypes[$customentry->extension]); 374 continue; 375 } 376 377 // Check required fields. 378 if (empty($customentry->type) || empty($customentry->icon)) { 379 debugging('Invalid $CFG->customfiletypes entry ' . $customentry->extension . 380 ' (type and icon fields required)', DEBUG_DEVELOPER); 381 continue; 382 } 383 384 // Build result array. 385 $result = array('type' => $customentry->type, 'icon' => $customentry->icon); 386 if (!empty($customentry->groups)) { 387 if (!is_array($customentry->groups)) { 388 debugging('Invalid $CFG->customfiletypes entry ' . $customentry->extension . 389 ' (groups field not array)', DEBUG_DEVELOPER); 390 continue; 391 } 392 $result['groups'] = $customentry->groups; 393 } 394 if (!empty($customentry->string)) { 395 if (!is_string($customentry->string)) { 396 debugging('Invalid $CFG->customfiletypes entry ' . $customentry->extension . 397 ' (string field not string)', DEBUG_DEVELOPER); 398 continue; 399 } 400 $result['string'] = $customentry->string; 401 } 402 if (!empty($customentry->defaulticon)) { 403 if (!is_bool($customentry->defaulticon)) { 404 debugging('Invalid $CFG->customfiletypes entry ' . $customentry->extension . 405 ' (defaulticon field not bool)', DEBUG_DEVELOPER); 406 continue; 407 } 408 $result['defaulticon'] = $customentry->defaulticon; 409 } 410 if (!empty($customentry->customdescription)) { 411 if (!is_string($customentry->customdescription)) { 412 debugging('Invalid $CFG->customfiletypes entry ' . $customentry->extension . 413 ' (customdescription field not string)', DEBUG_DEVELOPER); 414 continue; 415 } 416 // As the name suggests, this field is used only for custom entries. 417 $result['customdescription'] = $customentry->customdescription; 418 } 419 420 // Track whether it is a custom filetype or a modified existing 421 // filetype. 422 if (array_key_exists($customentry->extension, $mimetypes)) { 423 $result['modified'] = true; 424 } else { 425 $result['custom'] = true; 426 } 427 428 // Add result array to list. 429 $mimetypes[$customentry->extension] = $result; 430 } 431 432 self::$cachedtypes = $mimetypes; 433 return self::$cachedtypes; 434 } 435 436 /** 437 * Gets custom types from config variable, after decoding the JSON if required. 438 * 439 * @return array Array of custom types (empty array if none) 440 */ 441 protected static function get_custom_types() { 442 global $CFG; 443 if (!empty($CFG->customfiletypes)) { 444 if (is_array($CFG->customfiletypes)) { 445 // You can define this as an array in config.php... 446 return $CFG->customfiletypes; 447 } else { 448 // Or as a JSON string in the config table. 449 return json_decode($CFG->customfiletypes); 450 } 451 } else { 452 return array(); 453 } 454 } 455 456 /** 457 * Sets the custom types into config variable, encoding into JSON. 458 * 459 * @param array $types Array of custom types 460 * @throws coding_exception If the custom types are fixed in config.php. 461 */ 462 protected static function set_custom_types(array $types) { 463 global $CFG; 464 // Check the setting hasn't been forced. 465 if (array_key_exists('customfiletypes', $CFG->config_php_settings)) { 466 throw new coding_exception('Cannot set custom filetypes because they ' . 467 'are defined in config.php'); 468 } 469 if (empty($types)) { 470 unset_config('customfiletypes'); 471 } else { 472 set_config('customfiletypes', json_encode(array_values($types))); 473 } 474 475 // Clear the cached type list. 476 self::reset_caches(); 477 } 478 479 /** 480 * Clears the type cache. This is not needed in normal use as the 481 * set_custom_types function automatically clears the cache. Intended for 482 * use in unit tests. 483 */ 484 public static function reset_caches() { 485 self::$cachedtypes = null; 486 } 487 488 /** 489 * Gets the default types that have been deleted. Returns an array containing 490 * the defaults of all those types. 491 * 492 * @return array Array (same format as get_mimetypes_array) 493 */ 494 public static function get_deleted_types() { 495 $defaults = self::get_default_types(); 496 $deleted = array(); 497 foreach (self::get_custom_types() as $customentry) { 498 if (!empty($customentry->deleted)) { 499 $deleted[$customentry->extension] = $defaults[$customentry->extension]; 500 } 501 } 502 return $deleted; 503 } 504 505 /** 506 * Adds a new entry to the list of custom filetypes. 507 * 508 * @param string $extension File extension without dot, e.g. 'doc' 509 * @param string $mimetype MIME type e.g. 'application/msword' 510 * @param string $coreicon Core icon to use e.g. 'document' 511 * @param array $groups Array of group strings that this type belongs to 512 * @param string $corestring Custom lang string name in mimetypes.php 513 * @param string $customdescription Custom description (plain text/multilang) 514 * @param bool $defaulticon True if this should be the default icon for the type 515 * @throws coding_exception If the extension already exists, or otherwise invalid 516 */ 517 public static function add_type($extension, $mimetype, $coreicon, 518 array $groups = array(), $corestring = '', $customdescription = '', 519 $defaulticon = false) { 520 // Check for blank extensions or incorrectly including the dot. 521 $extension = (string)$extension; 522 if ($extension === '' || $extension[0] === '.') { 523 throw new coding_exception('Invalid extension .' . $extension); 524 } 525 526 // Check extension not already used. 527 $mimetypes = get_mimetypes_array(); 528 if (array_key_exists($extension, $mimetypes)) { 529 throw new coding_exception('Extension ' . $extension . ' already exists'); 530 } 531 532 // For default icon, check there isn't already something with default icon 533 // set for that MIME type. 534 if ($defaulticon) { 535 foreach ($mimetypes as $type) { 536 if ($type['type'] === $mimetype && !empty($type['defaulticon'])) { 537 throw new coding_exception('MIME type ' . $mimetype . 538 ' already has a default icon set'); 539 } 540 } 541 } 542 543 // Get existing custom filetype list. 544 $customs = self::get_custom_types(); 545 546 // Check if there's a 'deleted' entry for the extension, if so then get 547 // rid of it. 548 foreach ($customs as $key => $custom) { 549 if ($custom->extension === $extension) { 550 unset($customs[$key]); 551 } 552 } 553 554 // Set up config record for new type. 555 $newtype = self::create_config_record($extension, $mimetype, $coreicon, $groups, 556 $corestring, $customdescription, $defaulticon); 557 558 // See if there's a default value with this extension. 559 $needsadding = true; 560 $defaults = self::get_default_types(); 561 if (array_key_exists($extension, $defaults)) { 562 // If it has the same values, we don't need to add it. 563 $defaultvalue = $defaults[$extension]; 564 $modified = (array)$newtype; 565 unset($modified['extension']); 566 ksort($defaultvalue); 567 ksort($modified); 568 if ($modified === $defaultvalue) { 569 $needsadding = false; 570 } 571 } 572 573 // Add to array and set in config. 574 if ($needsadding) { 575 $customs[] = $newtype; 576 } 577 self::set_custom_types($customs); 578 } 579 580 /** 581 * Updates an entry in the list of filetypes in config. 582 * 583 * @param string $extension File extension without dot, e.g. 'doc' 584 * @param string $newextension New file extension (same if not changing) 585 * @param string $mimetype MIME type e.g. 'application/msword' 586 * @param string $coreicon Core icon to use e.g. 'document' 587 * @param array $groups Array of group strings that this type belongs to 588 * @param string $corestring Custom lang string name in mimetypes.php 589 * @param string $customdescription Custom description (plain text/multilang) 590 * @param bool $defaulticon True if this should be the default icon for the type 591 * @throws coding_exception If the new extension already exists, or otherwise invalid 592 */ 593 public static function update_type($extension, $newextension, $mimetype, $coreicon, 594 array $groups = array(), $corestring = '', $customdescription = '', 595 $defaulticon = false) { 596 597 // Extension must exist. 598 $extension = (string)$extension; 599 $mimetypes = get_mimetypes_array(); 600 if (!array_key_exists($extension, $mimetypes)) { 601 throw new coding_exception('Extension ' . $extension . ' not found'); 602 } 603 604 // If there's a new extension then this must not exist. 605 $newextension = (string)$newextension; 606 if ($newextension !== $extension) { 607 if ($newextension === '' || $newextension[0] === '.') { 608 throw new coding_exception('Invalid extension .' . $newextension); 609 } 610 if (array_key_exists($newextension, $mimetypes)) { 611 throw new coding_exception('Extension ' . $newextension . ' already exists'); 612 } 613 } 614 615 // For default icon, check there isn't already something with default icon 616 // set for that MIME type (unless it's this). 617 if ($defaulticon) { 618 foreach ($mimetypes as $ext => $type) { 619 if ($ext !== $extension && $type['type'] === $mimetype && 620 !empty($type['defaulticon'])) { 621 throw new coding_exception('MIME type ' . $mimetype . 622 ' already has a default icon set'); 623 } 624 } 625 } 626 627 // Delete the old extension and then add the new one (may be same). This 628 // will correctly handle cases when a default type is involved. 629 self::delete_type($extension); 630 self::add_type($newextension, $mimetype, $coreicon, $groups, $corestring, 631 $customdescription, $defaulticon); 632 } 633 634 /** 635 * Deletes a file type from the config list (or, for a standard one, marks it 636 * as deleted). 637 * 638 * @param string $extension File extension without dot, e.g. 'doc' 639 * @throws coding_exception If the extension does not exist, or otherwise invalid 640 */ 641 public static function delete_type($extension) { 642 // Extension must exist. 643 $mimetypes = get_mimetypes_array(); 644 if (!array_key_exists($extension, $mimetypes)) { 645 throw new coding_exception('Extension ' . $extension . ' not found'); 646 } 647 648 // Get existing custom filetype list. 649 $customs = self::get_custom_types(); 650 651 // Remove any entries for this extension. 652 foreach ($customs as $key => $custom) { 653 if ($custom->extension === $extension && empty($custom->deleted)) { 654 unset($customs[$key]); 655 } 656 } 657 658 // If it was a standard entry (doesn't have 'custom' set) then add a 659 // deleted marker. 660 if (empty($mimetypes[$extension]['custom'])) { 661 $customs[] = (object)array('extension' => $extension, 'deleted' => true); 662 } 663 664 // Save and reset cache. 665 self::set_custom_types($customs); 666 } 667 668 /** 669 * Reverts a file type to the default. May only be called on types that have 670 * default values. This will undelete the type if necessary or set its values. 671 * If the type is already at default values, does nothing. 672 * 673 * @param string $extension File extension without dot, e.g. 'doc' 674 * @return bool True if anything was changed, false if it was already default 675 * @throws coding_exception If the extension is not a default type. 676 */ 677 public static function revert_type_to_default($extension) { 678 $extension = (string)$extension; 679 680 // Check it actually is a default type. 681 $defaults = self::get_default_types(); 682 if (!array_key_exists($extension, $defaults)) { 683 throw new coding_exception('Extension ' . $extension . ' is not a default type'); 684 } 685 686 // Loop through all the custom settings. 687 $changed = false; 688 $customs = self::get_custom_types(); 689 foreach ($customs as $key => $customentry) { 690 if ($customentry->extension === $extension) { 691 unset($customs[$key]); 692 $changed = true; 693 } 694 } 695 696 // Save changes if any. 697 if ($changed) { 698 self::set_custom_types($customs); 699 } 700 return $changed; 701 } 702 703 /** 704 * Converts function parameters into a record for storing in the JSON value. 705 * 706 * @param string $extension File extension without dot, e.g. 'doc' 707 * @param string $mimetype MIME type e.g. 'application/msword' 708 * @param string $coreicon Core icon to use e.g. 'document' 709 * @param array $groups Array of group strings that this type belongs to 710 * @param string $corestring Custom lang string name in mimetypes.php 711 * @param string $customdescription Custom description (plain text/multilang) 712 * @param bool $defaulticon True if this should be the default icon for the type 713 * @return stdClass Record matching the parameters 714 */ 715 protected static function create_config_record($extension, $mimetype, 716 $coreicon, array $groups, $corestring, $customdescription, $defaulticon) { 717 // Construct new entry. 718 $newentry = (object)array('extension' => (string)$extension, 'type' => (string)$mimetype, 719 'icon' => (string)$coreicon); 720 if ($groups) { 721 if (!is_array($groups)) { 722 throw new coding_exception('Groups must be an array'); 723 } 724 foreach ($groups as $group) { 725 if (!is_string($group)) { 726 throw new coding_exception('Groups must be an array of strings'); 727 } 728 } 729 $newentry->groups = $groups; 730 } 731 if ($corestring) { 732 $newentry->string = (string)$corestring; 733 } 734 if ($customdescription) { 735 $newentry->customdescription = (string)$customdescription; 736 } 737 if ($defaulticon) { 738 $newentry->defaulticon = true; 739 } 740 return $newentry; 741 } 742 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body