. // // // /////////////////////////////////////////////////////////////////////////// defined('MOODLE_INTERNAL') || die(); /** * Rendering of files viewer related widgets. * @package core * @subpackage file * @copyright 2010 Dongsheng Cai * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @since Moodle 2.0 */ /** * File browser render * * @copyright 2010 Dongsheng Cai * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @since Moodle 2.0 */ class core_files_renderer extends plugin_renderer_base { public function files_tree_viewer(file_info $file_info, array $options = null) { $tree = new files_tree_viewer($file_info, $options); return $this->render($tree); } public function render_files_tree_viewer(files_tree_viewer $tree) { $html = $this->output->heading_with_help(get_string('coursefiles'), 'courselegacyfiles', 'moodle'); $html .= $this->output->container_start('coursefilesbreadcrumb'); foreach($tree->path as $path) { $html .= $path; $html .= ' / '; } $html .= $this->output->container_end(); $html .= $this->output->box_start(); $table = new html_table(); $table->head = array(get_string('name'), get_string('lastmodified'), get_string('size', 'repository'), get_string('type', 'repository')); $table->align = array('left', 'left', 'left', 'left'); $table->width = '100%'; $table->data = array(); foreach ($tree->tree as $file) { $filedate = $filesize = $filetype = ''; if ($file['filedate']) { $filedate = userdate($file['filedate'], get_string('strftimedatetimeshort', 'langconfig')); } if (empty($file['isdir'])) { if ($file['filesize']) { $filesize = display_size($file['filesize']); } $fileicon = file_file_icon($file, 24); $filetype = get_mimetype_description($file); } else { $fileicon = file_folder_icon(24); } $table->data[] = array( html_writer::link($file['url'], $this->output->pix_icon($fileicon, get_string('icon')) . ' ' . $file['filename']), $filedate, $filesize, $filetype ); } $html .= html_writer::table($table); $html .= $this->output->single_button(new moodle_url('/files/coursefilesedit.php', array('contextid'=>$tree->context->id)), get_string('coursefilesedit'), 'get'); $html .= $this->output->box_end(); return $html; } /** * Prints the file manager and initializes all necessary libraries * *
     * $fm = new form_filemanager($options);
     * $output = get_renderer('core', 'files');
     * echo $output->render($fm);
     * 
* * @param form_filemanager $fm File manager to render * @return string HTML fragment */ public function render_form_filemanager($fm) { $html = $this->fm_print_generallayout($fm); $module = array( 'name'=>'form_filemanager', 'fullpath'=>'/lib/form/filemanager.js', 'requires' => array('moodle-core-notification-dialogue', 'core_filepicker', 'base', 'io-base', 'node', 'json', 'core_dndupload', 'panel', 'resize-plugin', 'dd-plugin'), 'strings' => array( array('error', 'moodle'), array('info', 'moodle'), array('confirmdeletefile', 'repository'), array('draftareanofiles', 'repository'), array('entername', 'repository'), array('enternewname', 'repository'), array('invalidjson', 'repository'), array('popupblockeddownload', 'repository'), array('unknownoriginal', 'repository'), array('confirmdeletefolder', 'repository'), array('confirmdeletefilewithhref', 'repository'), array('confirmrenamefolder', 'repository'), array('confirmrenamefile', 'repository'), array('newfolder', 'repository'), array('edit', 'moodle') ) ); if ($this->page->requires->should_create_one_time_item_now('core_file_managertemplate')) { $this->page->requires->js_init_call('M.form_filemanager.set_templates', array($this->filemanager_js_templates()), true, $module); } $this->page->requires->js_init_call('M.form_filemanager.init', array($fm->options), true, $module); // non javascript file manager $html .= ''; return $html; } /** * Returns html for displaying one file manager * * @param form_filemanager $fm * @return string */ protected function fm_print_generallayout($fm) { $context = [ 'client_id' => $fm->options->client_id, 'helpicon' => $this->help_icon('setmainfile', 'repository'), 'restrictions' => $this->fm_print_restrictions($fm) ]; return $this->render_from_template('core/filemanager_page_generallayout', $context); } /** * FileManager JS template for displaying one file in 'icon view' mode. * * Except for elements described in fp_js_template_iconfilename, this template may also * contain element with class 'fp-contextmenu'. If context menu is available for this * file, the top element will receive the additional class 'fp-hascontextmenu' and * the element with class 'fp-contextmenu' will hold onclick event for displaying * the context menu. * * @see fp_js_template_iconfilename() * @return string */ protected function fm_js_template_iconfilename() { $rv = '
'.$this->pix_icon('i/menu', '▶').'
'; return $rv; } /** * FileManager JS template for displaying file name in 'table view' and 'tree view' modes. * * Except for elements described in fp_js_template_listfilename, this template may also * contain element with class 'fp-contextmenu'. If context menu is available for this * file, the top element will receive the additional class 'fp-hascontextmenu' and * the element with class 'fp-contextmenu' will hold onclick event for displaying * the context menu. * * @todo MDL-32736 remove onclick="return false;" * @see fp_js_template_listfilename() * @return string */ protected function fm_js_template_listfilename() { $rv = ' '.$this->pix_icon('i/menu', '▶').' '; return $rv; } /** * FileManager JS template for displaying 'Make new folder' dialog. * * Must be wrapped in an element, CSS for this element must define width and height of the window; * * Must have one input element with type="text" (for users to enter the new folder name); * * content of element with class 'fp-dlg-curpath' will be replaced with current path where * new folder is about to be created; * elements with classes 'fp-dlg-butcreate' and 'fp-dlg-butcancel' will hold onclick events; * * @return string */ protected function fm_js_template_mkdir() { $rv = ' '; return $rv; } /** * FileManager JS template for error/info message displayed as a separate popup window. * * @see fp_js_template_message() * @return string */ protected function fm_js_template_message() { return $this->fp_js_template_message(); } /** * FileManager JS template for window with file information/actions. * */ protected function fm_js_template_fileselectlayout() { $context = [ 'helpicon' => $this->help_icon('setmainfile', 'repository') ]; return $this->render_from_template('core/filemanager_fileselect', $context); } /** * FileManager JS template for popup confirm dialogue window. * * @return string */ protected function fm_js_template_confirmdialog() { return $this->render_from_template('core/filemanager_confirmdialog', []); } /** * Returns all FileManager JavaScript templates as an array. * * @return array */ public function filemanager_js_templates() { $class_methods = get_class_methods($this); $templates = array(); foreach ($class_methods as $method_name) { if (preg_match('/^fm_js_template_(.*)$/', $method_name, $matches)) $templates[$matches[1]] = $this->$method_name(); } return $templates; } /** * Displays restrictions for the file manager * * @param form_filemanager $fm * @return string */ protected function fm_print_restrictions($fm) { $maxbytes = display_size($fm->options->maxbytes); $strparam = (object) array('size' => $maxbytes, 'attachments' => $fm->options->maxfiles, 'areasize' => display_size($fm->options->areamaxbytes)); $hasmaxfiles = !empty($fm->options->maxfiles) && $fm->options->maxfiles > 0; $hasarealimit = !empty($fm->options->areamaxbytes) && $fm->options->areamaxbytes != -1; if ($hasmaxfiles && $hasarealimit) { $maxsize = get_string('maxsizeandattachmentsandareasize', 'moodle', $strparam); } else if ($hasmaxfiles) { $maxsize = get_string('maxsizeandattachments', 'moodle', $strparam); } else if ($hasarealimit) { $maxsize = get_string('maxsizeandareasize', 'moodle', $strparam); } else { $maxsize = get_string('maxfilesize', 'moodle', $maxbytes); } // TODO MDL-32020 also should say about 'File types accepted' return ''. $maxsize . ''; } /** * Template for FilePicker with general layout (not QuickUpload). * * * @return string */ protected function fp_js_template_generallayout() { return $this->render_from_template('core/filemanager_modal_generallayout', []); } /** * FilePicker JS template for displaying one file in 'icon view' mode. * * the element with class 'fp-thumbnail' will be resized to the repository thumbnail size * (both width and height, unless min-width and/or min-height is set in CSS) and the content of * an element will be replaced with an appropriate img; * * the width of element with class 'fp-filename' will be set to the repository thumbnail width * (unless min-width is set in css) and the content of an element will be replaced with filename * supplied by repository; * * top element(s) will have class fp-folder if the element is a folder; * * List of files will have parent
element with class 'fp-iconview' * * @return string */ protected function fp_js_template_iconfilename() { $rv = '

'; return $rv; } /** * FilePicker JS template for displaying file name in 'table view' and 'tree view' modes. * * content of the element with class 'fp-icon' will be replaced with an appropriate img; * * content of element with class 'fp-filename' will be replaced with filename supplied by * repository; * * top element(s) will have class fp-folder if the element is a folder; * * Note that tree view and table view are the YUI widgets and therefore there are no * other templates. The widgets will be wrapped in
with class fp-treeview or * fp-tableview (respectfully). * * @return string */ protected function fp_js_template_listfilename() { $rv = ' '; return $rv; } /** * FilePicker JS template for displaying link/loading progress for fetching of the next page * * This text is added to .fp-content AFTER .fp-iconview/.fp-treeview/.fp-tableview * * Must have one parent element with class 'fp-nextpage'. It will be assigned additional * class 'loading' during loading of the next page (it is recommended that in this case the link * becomes unavailable). Also must contain one element or
'; return $rv; } /** * FilePicker JS template for popup dialogue window asking for action when file with the same name already exists. * * @return string */ protected function fp_js_template_processexistingfile() { return $this->render_from_template('core/filemanager_processexistingfile', []); } /** * FilePicker JS template for popup dialogue window asking for action when file with the same name already exists * (multiple-file version). * * @return string */ protected function fp_js_template_processexistingfilemultiple() { return $this->render_from_template('core/filemanager_processexistingfilemultiple', []); } /** * FilePicker JS template for repository login form including templates for each element type * * @return string */ protected function fp_js_template_loginform() { return $this->render_from_template('core/filemanager_loginform', []); } /** * Returns all FilePicker JavaScript templates as an array. * * @return array */ public function filepicker_js_templates() { $class_methods = get_class_methods($this); $templates = array(); foreach ($class_methods as $method_name) { if (preg_match('/^fp_js_template_(.*)$/', $method_name, $matches)) $templates[$matches[1]] = $this->$method_name(); } return $templates; } /** * Returns HTML for default repository searchform to be passed to Filepicker * * This will be used as contents for search form defined in generallayout template * (form with id {TOOLSEARCHID}). * Default contents is one text input field with name="s" */ public function repository_default_searchform() { return $this->render_from_template('core/filemanager_default_searchform', []); } } /** * Data structure representing a general moodle file tree viewer * * @copyright 2010 Dongsheng Cai * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @since Moodle 2.0 */ class files_tree_viewer implements renderable { public $tree; public $path; public $context; /** * Constructor of moodle_file_tree_viewer class * @param file_info $file_info * @param array $options */ public function __construct(file_info $file_info, array $options = null) { global $CFG; //note: this MUST NOT use get_file_storage() !!!!!!!!!!!!!!!!!!!!!!!!!!!! $this->options = (array)$options; $this->context = $options['context']; $this->tree = array(); $children = $file_info->get_children(); $current_file_params = $file_info->get_params(); $parent_info = $file_info->get_parent(); $level = $parent_info; $this->path = array(); while ($level) { $params = $level->get_params(); $context = context::instance_by_id($params['contextid']); // $this->context is current context if ($context->id != $this->context->id or empty($params['filearea'])) { break; } // unset unused parameters unset($params['component']); unset($params['filearea']); unset($params['filename']); unset($params['itemid']); $url = new moodle_url('/files/index.php', $params); $this->path[] = html_writer::link($url, $level->get_visible_name()); $level = $level->get_parent(); } $this->path = array_reverse($this->path); if ($current_file_params['filepath'] != '/') { $this->path[] = $file_info->get_visible_name(); } foreach ($children as $child) { $filedate = $child->get_timemodified(); $filesize = $child->get_filesize(); $mimetype = $child->get_mimetype(); $params = $child->get_params(); unset($params['component']); unset($params['filearea']); unset($params['filename']); unset($params['itemid']); $fileitem = array( 'params' => $params, 'filename' => $child->get_visible_name(), 'mimetype' => $child->get_mimetype(), 'filedate' => $filedate ? $filedate : '', 'filesize' => $filesize ? $filesize : '' ); $url = new moodle_url('/files/index.php', $params); if ($child->is_directory()) { $fileitem['isdir'] = true; $fileitem['url'] = $url->out(false); } else { $fileitem['url'] = $child->get_url(); } $this->tree[] = $fileitem; } } }