diff --git a/admin/tool/filetypes/classes/utils.php b/admin/tool/filetypes/classes/utils.php new file mode 100644 index 00000000000..45a1c6b2790 --- /dev/null +++ b/admin/tool/filetypes/classes/utils.php @@ -0,0 +1,122 @@ +. + +/** + * Class with static back-end methods used by the file type tool. + * + * @package tool_filetypes + * @copyright 2014 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace tool_filetypes; + +defined('MOODLE_INTERNAL') || die(); + +/** + * Class with static back-end methods used by the file type tool. + * + * @package tool_filetypes + * @copyright 2014 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class utils { + /** + * Checks if the given file type extension is invalid. + * The added file type extension must be unique and must not begin with a dot. + * + * @param string $extension Extension of the file type to add + * @param string $oldextension Extension prior to update (empty string if adding new type) + * @return bool True if it the file type trying to add already exists + */ + public static function is_extension_invalid($extension, $oldextension = '') { + $extension = trim($extension); + if ($extension === '' || $extension[0] === '.') { + return true; + } + + $mimeinfo = get_mimetypes_array(); + if ($oldextension !== '') { + unset($mimeinfo[$oldextension]); + } + + return array_key_exists($extension, $mimeinfo); + } + + /** + * Checks if we are allowed to turn on the 'default icon' option. You can + * only have one of these for a given MIME type. + * + * @param string $mimetype MIME type + * @param string $oldextension File extension name (before any change) + */ + public static function is_defaulticon_allowed($mimetype, $oldextension = '') { + $mimeinfo = get_mimetypes_array(); + if ($oldextension !== '') { + unset($mimeinfo[$oldextension]); + } + foreach ($mimeinfo as $extension => $values) { + if ($values['type'] !== $mimetype) { + continue; + } + if (!empty($values['defaulticon'])) { + return false; + } + } + return true; + } + + /** + * Gets all unique file type icons from a specific path, not including + * sub-directories. + * + * Icon files such as pdf.png, pdf-24.png and pdf-36.png etc. are counted as + * the same icon type. + * + * The resultant array has both key and value set to the icon name prefix, + * such as 'pdf' => 'pdf'. + * + * @param string $path The path of the icon path + * @return array An array of unique file icons within the given path + */ + public static function get_icons_from_path($path) { + $icons = array(); + if ($handle = @opendir($path)) { + while (($file = readdir($handle)) !== false) { + $matches = array(); + if (preg_match('~(.+?)(?:-24|-32|-48|-64|-72|-80|-96|-128|-256)?\.(?:gif|png)$~', + $file, $matches)) { + $key = $matches[1]; + $icons[$key] = $key; + } + } + closedir($handle); + } + ksort($icons); + return $icons; + } + + /** + * Gets unique file type icons from pix/f folder. + * + * @return array An array of unique file type icons e.g. 'pdf' => 'pdf' + */ + public static function get_file_icons() { + global $CFG; + $path = $CFG->dirroot . '/pix/f'; + return self::get_icons_from_path($path); + } +} diff --git a/admin/tool/filetypes/delete.php b/admin/tool/filetypes/delete.php new file mode 100644 index 00000000000..8b73f2bceab --- /dev/null +++ b/admin/tool/filetypes/delete.php @@ -0,0 +1,60 @@ +. + +/** + * Delete a file type with a confirmation box. + * + * @package tool_filetypes + * @copyright 2014 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require(__DIR__ . '/../../../config.php'); +require_once($CFG->libdir . '/adminlib.php'); + +admin_externalpage_setup('tool_filetypes'); + +$extension = required_param('extension', PARAM_ALPHANUMEXT); +$redirecturl = new \moodle_url('/admin/tool/filetypes/index.php'); + +if (optional_param('delete', 0, PARAM_INT)) { + require_sesskey(); + + // Delete the file type from the config. + core_filetypes::delete_type($extension); + redirect($redirecturl); +} + +// Page settings. +$title = get_string('deletefiletypes', 'tool_filetypes'); + +$context = context_system::instance(); +$PAGE->set_url(new \moodle_url('/admin/tool/filetypes/delete.php', array('extension' => $extension))); +$PAGE->navbar->add($title); +$PAGE->set_context($context); +$PAGE->set_pagelayout('admin'); +$PAGE->set_title($SITE->fullname. ': ' . $title); + +// Display the page. +echo $OUTPUT->header(); + +$message = get_string('delete_confirmation', 'tool_filetypes', $extension); +$deleteurl = new \moodle_url('delete.php', array('extension' => $extension, 'delete' => 1)); +$yesbutton = new single_button($deleteurl, get_string('yes')); +$nobutton = new single_button($redirecturl, get_string('no'), 'get'); +echo $OUTPUT->confirm($message, $yesbutton, $nobutton); + +echo $OUTPUT->footer(); diff --git a/admin/tool/filetypes/edit.php b/admin/tool/filetypes/edit.php new file mode 100644 index 00000000000..33d934bee1d --- /dev/null +++ b/admin/tool/filetypes/edit.php @@ -0,0 +1,111 @@ +. + +/** + * Display the file type updating page. + * + * @package tool_filetypes + * @copyright 2014 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +require(__DIR__ . '/../../../config.php'); +require_once($CFG->libdir . '/adminlib.php'); +require_once('edit_form.php'); + +admin_externalpage_setup('tool_filetypes'); + +$oldextension = optional_param('oldextension', '', PARAM_ALPHANUMEXT); +$mform = new tool_filetypes_form('edit.php', array('oldextension' => $oldextension)); +$title = get_string('addfiletypes', 'tool_filetypes'); + +if ($oldextension) { + // This is editing an existing filetype, load data to the form. + $mimetypes = get_mimetypes_array(); + if (!array_key_exists($oldextension, $mimetypes)) { + throw new moodle_exception('error_notfound', 'tool_filetypes'); + } + $typeinfo = $mimetypes[$oldextension]; + $formdata = array( + 'extension' => $oldextension, + 'mimetype' => $typeinfo['type'], + 'icon' => $typeinfo['icon'], + 'oldextension' => $oldextension, + 'description' => '', + 'groups' => '', + 'corestring' => '', + 'defaulticon' => 0 + ); + if (!empty($typeinfo['customdescription'])) { + $formdata['description'] = $typeinfo['customdescription']; + } + if (!empty($typeinfo['groups'])) { + $formdata['groups'] = implode(', ', $typeinfo['groups']); + } + if (!empty($typeinfo['string'])) { + $formdata['corestring'] = $typeinfo['string']; + } + if (!empty($typeinfo['defaulticon'])) { + $formdata['defaulticon'] = 1; + } + + $mform->set_data($formdata); + $title = get_string('editfiletypes', 'tool_filetypes'); +} + +$backurl = new \moodle_url('/admin/tool/filetypes/index.php'); +if ($mform->is_cancelled()) { + redirect($backurl); +} else if ($data = $mform->get_data()) { + // Convert the groups value back into an array. + $data->groups = trim($data->groups); + if ($data->groups) { + $data->groups = preg_split('~,\s*~', $data->groups); + } else { + $data->groups = array(); + } + if (empty($data->defaulticon)) { + $data->defaulticon = 0; + } + if (empty($data->corestring)) { + $data->corestring = ''; + } + if (empty($data->description)) { + $data->description = ''; + } + if ($data->oldextension) { + // Update an existing file type. + core_filetypes::update_type($data->oldextension, $data->extension, $data->mimetype, $data->icon, + $data->groups, $data->corestring, $data->description, (bool)$data->defaulticon); + } else { + // Add a new file type entry. + core_filetypes::add_type($data->extension, $data->mimetype, $data->icon, + $data->groups, $data->corestring, $data->description, (bool)$data->defaulticon); + } + redirect($backurl); +} + +// Page settings. +$context = context_system::instance(); +$PAGE->set_url(new \moodle_url('/admin/tool/filetypes/edit.php', array('oldextension' => $oldextension))); +$PAGE->navbar->add($oldextension ? s($oldextension) : $title); +$PAGE->set_context($context); +$PAGE->set_pagelayout('admin'); +$PAGE->set_title($SITE->fullname. ': ' . $title); + +// Display the page. +echo $OUTPUT->header(); +$mform->display(); +echo $OUTPUT->footer(); diff --git a/admin/tool/filetypes/edit_form.php b/admin/tool/filetypes/edit_form.php new file mode 100644 index 00000000000..5d16177212f --- /dev/null +++ b/admin/tool/filetypes/edit_form.php @@ -0,0 +1,115 @@ +. + +/** + * Customised file types editing form. + * + * @package tool_filetypes + * @copyright 2014 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require_once($CFG->dirroot . '/lib/formslib.php'); + +/** + * Form for adding a new custom file type or updating an existing custom file type. + * + * @package tool_filetypes + * @copyright 2014 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class tool_filetypes_form extends moodleform { + + public function definition() { + global $CFG; + $mform = $this->_form; + $oldextension = $this->_customdata['oldextension']; + + $mform->addElement('text', 'extension', get_string('extension', 'tool_filetypes')); + $mform->setType('extension', PARAM_ALPHANUMEXT); + $mform->addRule('extension', null, 'required', null, 'client'); + $mform->addHelpButton('extension', 'extension', 'tool_filetypes'); + + $mform->addElement('text', 'mimetype', get_string('mimetype', 'tool_filetypes')); + $mform->setType('mimetype', PARAM_RAW); + $mform->addRule('mimetype', null, 'required', null, 'client'); + $mform->addHelpButton('mimetype', 'mimetype', 'tool_filetypes'); + + $fileicons = \tool_filetypes\utils::get_file_icons(); + $mform->addElement('select', 'icon', + get_string('icon', 'tool_filetypes'), $fileicons); + $mform->addHelpButton('icon', 'icon', 'tool_filetypes'); + + $mform->addElement('text', 'groups', get_string('groups', 'tool_filetypes')); + $mform->setType('groups', PARAM_RAW); + $mform->addHelpButton('groups', 'groups', 'tool_filetypes'); + + $mform->addElement('select', 'descriptiontype', get_string('descriptiontype', 'tool_filetypes'), + array('' => get_string('descriptiontype_default', 'tool_filetypes'), + 'custom' => get_string('descriptiontype_custom', 'tool_filetypes'), + 'lang' => get_string('descriptiontype_lang', 'tool_filetypes'))); + + $mform->addElement('text', 'description', get_string('description', 'tool_filetypes')); + $mform->setType('description', PARAM_TEXT); + $mform->addHelpButton('description', 'description', 'tool_filetypes'); + $mform->disabledIf('description', 'descriptiontype', 'ne', 'custom'); + + $mform->addElement('text', 'corestring', get_string('corestring', 'tool_filetypes')); + $mform->setType('corestring', PARAM_ALPHANUMEXT); + $mform->addHelpButton('corestring', 'corestring', 'tool_filetypes'); + $mform->disabledIf('corestring', 'descriptiontype', 'ne', 'lang'); + + $mform->addElement('checkbox', 'defaulticon', get_string('defaulticon', 'tool_filetypes')); + $mform->addHelpButton('defaulticon', 'defaulticon', 'tool_filetypes'); + + $mform->addElement('hidden', 'oldextension', $oldextension); + $mform->setType('oldextension', PARAM_RAW); + $this->add_action_buttons(true, get_string('savechanges')); + } + + public function set_data($data) { + // Set up the description type. + if (!empty($data['corestring'])) { + $data['descriptiontype'] = 'lang'; + } else if (!empty($data['description'])) { + $data['descriptiontype'] = 'custom'; + } else { + $data['descriptiontype'] = ''; + } + + // Call parent. + parent::set_data($data); + } + + public function validation($data, $files) { + $errors = parent::validation($data, $files); + + // Check the extension isn't already in use. + $oldextension = $data['oldextension']; + $extension = trim($data['extension']); + if (\tool_filetypes\utils::is_extension_invalid($extension, $oldextension)) { + $errors['extension'] = get_string('error_extension', 'tool_filetypes', $extension); + } + + // Check the 'default icon' setting doesn't conflict with an existing one. + if (!empty($data['defaulticon']) && !\tool_filetypes\utils::is_defaulticon_allowed( + $data['mimetype'], $oldextension)) { + $errors['defaulticon'] = get_string('error_defaulticon', 'tool_filetypes', $extension); + } + + return $errors; + } +} diff --git a/admin/tool/filetypes/index.php b/admin/tool/filetypes/index.php new file mode 100644 index 00000000000..6ac20dcd682 --- /dev/null +++ b/admin/tool/filetypes/index.php @@ -0,0 +1,48 @@ +. + +/** + * Display the custom file type settings page. + * + * @package tool_filetypes + * @copyright 2014 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require(__DIR__ . '/../../../config.php'); +require_once($CFG->libdir . '/adminlib.php'); + +admin_externalpage_setup('tool_filetypes'); + +// Page settings. +$title = get_string('pluginname', 'tool_filetypes'); + +$context = context_system::instance(); +$PAGE->set_url(new \moodle_url('/admin/tool/filetypes/index.php')); +$PAGE->set_context($context); +$PAGE->set_pagelayout('admin'); +$PAGE->set_title($SITE->fullname. ': ' . $title); + +$renderer = $PAGE->get_renderer('tool_filetypes'); + +// Is it restricted because set in config.php? +$restricted = array_key_exists('customfiletypes', $CFG->config_php_settings); + +// Display the page. +echo $renderer->header(); +echo $renderer->edit_table(get_mimetypes_array(), core_filetypes::get_deleted_types(), + $restricted); +echo $renderer->footer(); diff --git a/admin/tool/filetypes/lang/en/tool_filetypes.php b/admin/tool/filetypes/lang/en/tool_filetypes.php new file mode 100644 index 00000000000..2640b44f7d3 --- /dev/null +++ b/admin/tool/filetypes/lang/en/tool_filetypes.php @@ -0,0 +1,69 @@ +. + +/** + * Strings for custom file types. + * + * @package tool_filetypes + * @copyright 2014 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +$string['addfiletypes'] = 'Add a new file type'; +$string['corestring'] = 'Alternative language string'; +$string['corestring_help'] = 'This setting can be used to select a different language string from the core mimetypes.php language file. Generally it should be left blank. For custom types, use the description field.'; +$string['defaulticon'] = 'Default icon for MIME type'; +$string['defaulticon_help'] = 'If there are multiple file extensions with the same MIME type, select this option for one of the extensions so that its icon will be used when determining an icon from the MIME type.'; +$string['delete_confirmation'] = 'Are you absolutely sure you want to remove .{$a}?'; +$string['deletea'] = 'Delete {$a}'; +$string['deletefiletypes'] = 'Delete a file type'; +$string['description'] = 'Custom description'; +$string['description_help'] = 'Simple file type description, e.g. ‘Kindle ebook’. If your site supports multiple languages and uses the multi-language filter, you can enter multi-language tags in this field to supply a description in different languages.'; +$string['descriptiontype'] = 'Description type'; +$string['descriptiontype_help'] = 'There are three possible ways to specify a description. + +* Default behaviour uses the MIME type. If there is a language string in mimetypes.php corresponding to that MIME type, it will be used; otherwise the MIME type itself will be displayed to users. +* You can specify a custom description on this form. +* You can specify the name of a languge string in mimetypes.php to use instead of the MIME type.'; +$string['descriptiontype_default'] = 'Default (MIME type or corresponding language string if available)'; +$string['descriptiontype_custom'] = 'Custom description specified in this form'; +$string['descriptiontype_lang'] = 'Alternative language string (from mimetypes.php)'; +$string['displaydescription'] = 'Description'; +$string['editfiletypes'] = 'Edit an existing file type'; +$string['emptylist'] = 'There are no file types defined.'; +$string['error_addentry'] = 'The file type extension, description, MIME type, and icon must not contain line feed and semicolon characters.'; +$string['error_defaulticon'] = 'Another file extension with the same MIME type is already marked as the default icon.'; +$string['error_extension'] = 'The file type extension {$a} already exists or is invalid. File extensions must be unique and must not contain special characters.'; +$string['error_notfound'] = 'The file type with extension {$a} cannot be found.'; +$string['extension'] = 'Extension'; +$string['extension_help'] = 'File name extension without the dot, e.g. ‘mobi’'; +$string['groups'] = 'Type groups'; +$string['groups_help'] = 'Optional list of file type groups that this type belongs to. These are generic categories such as ‘document’ and ‘image’.'; +$string['icon'] = 'File icon'; +$string['icon_help'] = 'Icon filename. + +The list of icons is taken from the /pix/f directory inside your Moodle installation. You can add custom icons to this folder if required.'; +$string['mimetype'] = 'MIME type'; +$string['mimetype_help'] = 'MIME type associated with this file type, e.g. ‘application/x-mobipocket-ebook’'; +$string['pluginname'] = 'File types'; +$string['revert'] = 'Restore {$a} to Moodle defaults'; +$string['revert_confirmation'] = 'Are you sure you want to restore .{$a} to Moodle defaults, discarding your changes?'; +$string['revertfiletype'] = 'Restore a file type'; +$string['source'] = 'Type'; +$string['source_custom'] = 'Custom'; +$string['source_deleted'] = 'Deleted'; +$string['source_modified'] = 'Modified'; +$string['source_standard'] = 'Standard'; diff --git a/admin/tool/filetypes/renderer.php b/admin/tool/filetypes/renderer.php new file mode 100644 index 00000000000..dee5281585f --- /dev/null +++ b/admin/tool/filetypes/renderer.php @@ -0,0 +1,179 @@ +. + +/** + * Renderer. + * + * @package tool_filetypes + * @copyright 2014 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +/** + * Class containing the renderer functions for displaying file types. + * + * @package tool_filetypes + * @copyright 2014 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class tool_filetypes_renderer extends plugin_renderer_base { + + /** + * Renderer for displaying the file type edit table. + * + * @param array $filetypes An array of file type objects (from get_mimetypes_array) + * @param array $deleted An array of deleted file types + * @param bool $restricted If true, cannot be edited because set in config.php. + * @return string HTML code + */ + public function edit_table(array $filetypes, array $deleted, $restricted) { + // Get combined array of all types, with deleted marker. + $combined = array_merge($filetypes, $deleted); + foreach ($deleted as $ext => $value) { + $combined[$ext]['deleted'] = true; + } + ksort($combined); + + $out = $this->heading(get_string('pluginname', 'tool_filetypes')); + if ($restricted) { + $out .= html_writer::div( + html_writer::div(get_string('configoverride', 'admin'), 'form-overridden'), + '', array('id' => 'adminsettings')); + } + if (count($combined) > 1) { + // Display the file type table if any file types exist (other than 'xxx'). + $table = new html_table(); + $headings = new html_table_row(); + $headings->cells = array(); + $headings->cells[] = new html_table_cell(get_string('extension', 'tool_filetypes')); + if (!$restricted) { + $headings->cells[] = + new html_table_cell(html_writer::span(get_string('edit'), 'accesshide')); + } + $headings->cells[] = new html_table_cell(get_string('source', 'tool_filetypes')); + $headings->cells[] = new html_table_cell(get_string('mimetype', 'tool_filetypes')); + $headings->cells[] = new html_table_cell(get_string('groups', 'tool_filetypes')); + $headings->cells[] = new html_table_cell(get_string('displaydescription', 'tool_filetypes')); + foreach ($headings->cells as $cell) { + $cell->header = true; + } + $table->data = array($headings); + foreach ($combined as $extension => $filetype) { + if ($extension === 'xxx') { + continue; + } + $row = new html_table_row(); + $row->cells = array(); + + // First cell has icon and extension. + $icon = $this->pix_icon('f/' . $filetype['icon'], ''); + $row->cells[] = new html_table_cell($icon . ' ' . html_writer::span(s($extension))); + + // Reset URL and button if needed. + $reverturl = new \moodle_url('/admin/tool/filetypes/revert.php', + array('extension' => $extension)); + $revertbutton = html_writer::link($reverturl, $this->pix_icon('t/restore', + get_string('revert', 'tool_filetypes', s($extension)))); + if ($restricted) { + $revertbutton = ''; + } + + // Rest is different for deleted items. + if (!empty($filetype['deleted'])) { + // Show deleted standard types differently. + if (!$restricted) { + $row->cells[] = new html_table_cell(''); + } + $source = new html_table_cell(get_string('source_deleted', 'tool_filetypes') . + ' ' . $revertbutton); + $source->attributes = array('class' => 'nonstandard'); + $row->cells[] = $source; + + // Other cells are blank. + $row->cells[] = new html_table_cell(''); + $row->cells[] = new html_table_cell(''); + $row->cells[] = new html_table_cell(''); + $row->attributes = array('class' => 'deleted'); + } else { + if (!$restricted) { + // Edit icons. For accessibility, the name of these links should + // be different for each row, so we have to include the extension. + $editurl = new \moodle_url('/admin/tool/filetypes/edit.php', + array('oldextension' => $extension)); + $editbutton = html_writer::link($editurl, $this->pix_icon('t/edit', + get_string('edita', '', s($extension)))); + $deleteurl = new \moodle_url('/admin/tool/filetypes/delete.php', + array('extension' => $extension)); + $deletebutton = html_writer::link($deleteurl, $this->pix_icon('t/delete', + get_string('deletea', 'tool_filetypes', s($extension)))); + $row->cells[] = new html_table_cell($editbutton . ' ' . $deletebutton); + } + + // Source. + $sourcestring = 'source_'; + if (!empty($filetype['custom'])) { + $sourcestring .= 'custom'; + } else if (!empty($filetype['modified'])) { + $sourcestring .= 'modified'; + } else { + $sourcestring .= 'standard'; + } + $source = new html_table_cell(get_string($sourcestring, 'tool_filetypes') . + ($sourcestring === 'source_modified' ? ' ' . $revertbutton : '')); + if ($sourcestring !== 'source_standard') { + $source->attributes = array('class' => 'nonstandard'); + } + $row->cells[] = $source; + + // MIME type. + $mimetype = html_writer::div(s($filetype['type']), 'mimetype'); + if (!empty($filetype['defaulticon'])) { + // Include the 'default for MIME type' info in the MIME type cell. + $mimetype .= html_writer::div(html_writer::tag('i', + get_string('defaulticon', 'tool_filetypes'))); + } + $row->cells[] = new html_table_cell($mimetype); + + // Groups. + $groups = !empty($filetype['groups']) ? implode(', ', $filetype['groups']) : ''; + $row->cells[] = new html_table_cell(s($groups)); + + // Description. + $description = get_mimetype_description(array('filename' => 'a.' . $extension)); + // Don't show the description if it's just a copy of the MIME type, + // it makes the table ugly with the long duplicate text; leave blank instead. + if ($description === $filetype['type']) { + $description = ''; + } + $row->cells[] = new html_table_cell($description); + } + + $table->data[] = $row; + } + $out .= html_writer::table($table); + } else { + $out .= html_writer::tag('div', get_string('emptylist', 'tool_filetypes')); + } + // Displaying the 'Add' button. + if (!$restricted) { + $out .= $this->single_button(new moodle_url('/admin/tool/filetypes/edit.php', + array('name' => 'add')), get_string('addfiletypes', 'tool_filetypes'), 'get'); + } + return $out; + } +} diff --git a/admin/tool/filetypes/revert.php b/admin/tool/filetypes/revert.php new file mode 100644 index 00000000000..549f460371d --- /dev/null +++ b/admin/tool/filetypes/revert.php @@ -0,0 +1,60 @@ +. + +/** + * Resets a file type to the default Moodle values. + * + * @package tool_filetypes + * @copyright 2014 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require(__DIR__ . '/../../../config.php'); +require_once($CFG->libdir . '/adminlib.php'); + +admin_externalpage_setup('tool_filetypes'); + +$extension = required_param('extension', PARAM_RAW); +$redirecturl = new \moodle_url('/admin/tool/filetypes/index.php'); + +if (optional_param('revert', 0, PARAM_INT)) { + require_sesskey(); + + // Reset the file type in config. + core_filetypes::revert_type_to_default($extension); + redirect($redirecturl); +} + +// Page settings. +$title = get_string('revertfiletype', 'tool_filetypes'); + +$context = context_system::instance(); +$PAGE->set_url(new \moodle_url('/admin/tool/filetypes/revert.php', array('extension' => $extension))); +$PAGE->navbar->add($title); +$PAGE->set_context($context); +$PAGE->set_pagelayout('admin'); +$PAGE->set_title($SITE->fullname. ': ' . $title); + +// Display the page. +echo $OUTPUT->header(); + +$message = get_string('revert_confirmation', 'tool_filetypes', $extension); +$reverturl = new \moodle_url('revert.php', array('extension' => $extension, 'revert' => 1)); +$yesbutton = new single_button($reverturl, get_string('yes')); +$nobutton = new single_button($redirecturl, get_string('no'), 'get'); +echo $OUTPUT->confirm($message, $yesbutton, $nobutton); + +echo $OUTPUT->footer(); diff --git a/admin/tool/filetypes/settings.php b/admin/tool/filetypes/settings.php new file mode 100644 index 00000000000..2028b0dd1e7 --- /dev/null +++ b/admin/tool/filetypes/settings.php @@ -0,0 +1,31 @@ +. + +/** + * Configure the setting page of the custom file type as an external page. + * + * @package tool_filetypes + * @copyright 2014 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die; + +if ($hassiteconfig) { + $ADMIN->add('server', new admin_externalpage('tool_filetypes', + new lang_string('pluginname', 'tool_filetypes'), + $CFG->wwwroot . '/admin/tool/filetypes/index.php')); +} diff --git a/admin/tool/filetypes/styles.css b/admin/tool/filetypes/styles.css new file mode 100644 index 00000000000..ed2353ab9fd --- /dev/null +++ b/admin/tool/filetypes/styles.css @@ -0,0 +1,32 @@ +/** + * Styles for admin tool page. + */ + +/* Fix bad default table wrap (caused by the long mimetype field). */ +.path-admin-tool-filetypes .generaltable .c0, +.path-admin-tool-filetypes .generaltable .c1, +.path-admin-tool-filetypes .generaltable .c2, +.path-admin-tool-filetypes .generaltable th { + white-space: nowrap; +} + +/* Formatting for deleted lines. */ +.path-admin-tool-filetypes .generaltable .deleted .c0 img { + opacity: 0.2; +} + +.path-admin-tool-filetypes .generaltable .deleted .c0 span { + text-decoration: line-through; +} + +/* Custom types show bold */ +.path-admin-tool-filetypes .generaltable .nonstandard { + font-weight: bold; +} + +/* Spacing around the 'Defined in config.php' stripe */ +.path-admin-tool-filetypes .form-overridden { + display: inline-block; + margin-bottom: 1em; + padding: 4px 6px; +} diff --git a/admin/tool/filetypes/tests/behat/add_filetypes.feature b/admin/tool/filetypes/tests/behat/add_filetypes.feature new file mode 100644 index 00000000000..18d043e91c2 --- /dev/null +++ b/admin/tool/filetypes/tests/behat/add_filetypes.feature @@ -0,0 +1,107 @@ +@tool @tool_filetypes +Feature: Add customised file types + In order to support a file mime type which doesn't exist in Moodle + As an administrator + I need to add a new customised file type + + Scenario: Add a new file type + Given I log in as "admin" + And I navigate to "File types" node in "Site administration > Server" + And I press "Add" + # Try setting all the form fields, not just the optional ones. + And I set the following fields to these values: + | Extension | frog | + | MIME type | application/x-frog | + | File icon | archive | + | Type groups | document | + | Description type | Custom description specified in this form | + | Custom description | Froggy file | + | Default icon for MIME type | 1 | + When I press "Save changes" + Then I should see "Froggy file" in the "application/x-frog" "table_row" + And I should see "document" in the "application/x-frog" "table_row" + And I should see "frog" in the "application/x-frog" "table_row" + And "//img[contains(@src, 'archive')]" "xpath_element" should exist in the "application/x-frog" "table_row" + + Scenario: Update an existing file type + Given I log in as "admin" + And I navigate to "File types" node in "Site administration > Server" + When I click on "Edit 7z" "link" + And I set the following fields to these values: + | Extension | doc | + And I press "Save changes" + Then I should see "File extensions must be unique" + And I set the following fields to these values: + | Extension | frog | + And I press "Save changes" + And I should see "frog" in the "application/x-7z-compressed" "table_row" + + Scenario: Delete an existing file type + Given I log in as "admin" + And I navigate to "File types" node in "Site administration > Server" + When I click on "Delete 7z" "link" + Then I should see "Are you absolutely sure you want to remove .7z?" + And I press "Yes" + And I should see "Deleted" in the "7z" "table_row" + + Scenario: Delete a custom file type + Given I log in as "admin" + And I navigate to "File types" node in "Site administration > Server" + And I press "Add" + And I set the following fields to these values: + | Extension | frog | + | MIME type | application/x-frog | + And I press "Save changes" + When I click on "Delete frog" "link" + And I press "Yes" + Then I should not see "frog" + + Scenario: Revert changes to deleted file type + Given I log in as "admin" + And I navigate to "File types" node in "Site administration > Server" + When I click on "Delete 7z" "link" + And I press "Yes" + And I follow "Restore 7z to Moodle defaults" + And I press "Yes" + Then I should not see "Deleted" in the "7z" "table_row" + + Scenario: Revert changes to updated file type + Given I log in as "admin" + And I navigate to "File types" node in "Site administration > Server" + And I click on "Edit 7z" "link" + And I set the following fields to these values: + | File icon | document | + And I press "Save changes" + When I follow "Restore 7z to Moodle defaults" + And I press "Yes" + Then "//img[contains(@src, 'archive')]" "xpath_element" should exist in the "7z" "table_row" + + @javascript + Scenario: Create a resource activity which contains a customised file type + Given the following "courses" exist: + | fullname | shortname | + | Course 1 | C1 | + And I log in as "admin" + And I navigate to "File types" node in "Site administration > Server" + And I press "Add" + And I set the following fields to these values: + | Extension | frog | + | MIME type | application/x-frog | + | File icon | archive | + | Description type | Custom description specified in this form | + | Custom description | Froggy file | + And I press "Save changes" + # Create a resource activity and add it to a course + And I am on homepage + And I follow "Course 1" + And I turn editing mode on + When I add a "File" to section "1" + And I set the following fields to these values: + | Name | An example of customised file type | + | Description | File description | + And I upload "admin/tool/filetypes/tests/fixtures/test.frog" file to "Select files" filemanager + And I expand all fieldsets + And I set the field "Show type" to "1" + And I press "Save and return to course" + Then I should see "Froggy file" + And the "src" attribute of ".modtype_resource a img" "css_element" should contain "archive" diff --git a/admin/tool/filetypes/tests/fixtures/frog-24.png b/admin/tool/filetypes/tests/fixtures/frog-24.png new file mode 100644 index 00000000000..91a99b94e23 Binary files /dev/null and b/admin/tool/filetypes/tests/fixtures/frog-24.png differ diff --git a/admin/tool/filetypes/tests/fixtures/frog-48.png b/admin/tool/filetypes/tests/fixtures/frog-48.png new file mode 100644 index 00000000000..91a99b94e23 Binary files /dev/null and b/admin/tool/filetypes/tests/fixtures/frog-48.png differ diff --git a/admin/tool/filetypes/tests/fixtures/test.frog b/admin/tool/filetypes/tests/fixtures/test.frog new file mode 100644 index 00000000000..f9819bb6649 --- /dev/null +++ b/admin/tool/filetypes/tests/fixtures/test.frog @@ -0,0 +1 @@ +This is not a real file format. \ No newline at end of file diff --git a/admin/tool/filetypes/tests/fixtures/zombie.gif b/admin/tool/filetypes/tests/fixtures/zombie.gif new file mode 100644 index 00000000000..9884f476b9c Binary files /dev/null and b/admin/tool/filetypes/tests/fixtures/zombie.gif differ diff --git a/admin/tool/filetypes/tests/tool_filetypes_test.php b/admin/tool/filetypes/tests/tool_filetypes_test.php new file mode 100644 index 00000000000..6d536835d4e --- /dev/null +++ b/admin/tool/filetypes/tests/tool_filetypes_test.php @@ -0,0 +1,86 @@ +. + +/** + * Unit tests for the custom file types. + * + * @package tool_filetypes + * @copyright 2014 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +use tool_filetypes\utils; + +/** + * Unit tests for the custom file types. + * + * @package tool_filetypes + * @copyright 2014 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class tool_filetypes_test extends advanced_testcase { + /** + * Tests is_extension_invalid() function. + */ + public function test_is_extension_invalid() { + // The pdf file extension already exists in default moodle minetypes. + $this->assertTrue(utils::is_extension_invalid('pdf')); + + // The frog extension does not. + $this->assertFalse(utils::is_extension_invalid('frog')); + + // However you could use the pdf extension when editing the pdf extension. + $this->assertFalse(utils::is_extension_invalid('pdf', 'pdf')); + + // Blank extension is invalid. + $this->assertTrue(utils::is_extension_invalid('')); + + // Extensions with dot are invalid. + $this->assertTrue(utils::is_extension_invalid('.frog')); + } + + /** + * Tests is_defaulticon_allowed() function. + */ + public function test_is_defaulticon_allowed() { + // You ARE allowed to set a default icon for a MIME type that hasn't + // been used yet. + $this->assertTrue(utils::is_defaulticon_allowed('application/x-frog')); + + // You AREN'T allowed to set default icon for text/plain as there is + // already a type that has that set. + $this->assertFalse(utils::is_defaulticon_allowed('text/plain')); + + // But you ARE still allowed to set it when actually editing txt, which + // is the default. + $this->assertTrue(utils::is_defaulticon_allowed('text/plain', 'txt')); + } + + /** + * Tests get_icons_from_path() function. + */ + public function test_get_icons_from_path() { + // Get icons from the fixtures folder. + $icons = utils::get_icons_from_path(__DIR__ . '/fixtures'); + + // The icons are returned alphabetically and with keys === values. + // For the icon with numbers after the name, only the base name is + // returned and only one of it. + $this->assertEquals(array('frog' => 'frog', 'zombie' => 'zombie'), $icons); + } +} diff --git a/admin/tool/filetypes/version.php b/admin/tool/filetypes/version.php new file mode 100644 index 00000000000..f4cefec69b0 --- /dev/null +++ b/admin/tool/filetypes/version.php @@ -0,0 +1,29 @@ +. + +/** + * Version details. + * + * @package tool_filetypes + * @copyright 2014 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +$plugin->version = 2014112700; +$plugin->requires = 2014112700; +$plugin->component = 'tool_filetypes';