renderer.php 52 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149
  1. <?php
  2. ///////////////////////////////////////////////////////////////////////////
  3. // //
  4. // This file is part of Moodle - http://moodle.org/ //
  5. // Moodle - Modular Object-Oriented Dynamic Learning Environment //
  6. // //
  7. // Moodle is free software: you can redistribute it and/or modify //
  8. // it under the terms of the GNU General Public License as published by //
  9. // the Free Software Foundation, either version 3 of the License, or //
  10. // (at your option) any later version. //
  11. // //
  12. // Moodle is distributed in the hope that it will be useful, //
  13. // but WITHOUT ANY WARRANTY; without even the implied warranty of //
  14. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
  15. // GNU General Public License for more details. //
  16. // //
  17. // You should have received a copy of the GNU General Public License //
  18. // along with Moodle. If not, see <http://www.gnu.org/licenses/>. //
  19. // //
  20. ///////////////////////////////////////////////////////////////////////////
  21. defined('MOODLE_INTERNAL') || die();
  22. /**
  23. * Rendering of files viewer related widgets.
  24. * @package core
  25. * @subpackage file
  26. * @copyright 2010 Dongsheng Cai
  27. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  28. * @since Moodle 2.0
  29. */
  30. /**
  31. * File browser render
  32. *
  33. * @copyright 2010 Dongsheng Cai
  34. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  35. * @since Moodle 2.0
  36. */
  37. class core_files_renderer extends plugin_renderer_base {
  38. public function files_tree_viewer(file_info $file_info, array $options = null) {
  39. $tree = new files_tree_viewer($file_info, $options);
  40. return $this->render($tree);
  41. }
  42. public function render_files_tree_viewer(files_tree_viewer $tree) {
  43. $html = $this->output->heading_with_help(get_string('coursefiles'), 'courselegacyfiles', 'moodle');
  44. $html .= $this->output->container_start('coursefilesbreadcrumb');
  45. foreach($tree->path as $path) {
  46. $html .= $path;
  47. $html .= ' / ';
  48. }
  49. $html .= $this->output->container_end();
  50. $html .= $this->output->box_start();
  51. $table = new html_table();
  52. $table->head = array(get_string('name'), get_string('lastmodified'), get_string('size', 'repository'), get_string('type', 'repository'));
  53. $table->align = array('left', 'left', 'left', 'left');
  54. $table->width = '100%';
  55. $table->data = array();
  56. foreach ($tree->tree as $file) {
  57. $filedate = $filesize = $filetype = '';
  58. if ($file['filedate']) {
  59. $filedate = userdate($file['filedate'], get_string('strftimedatetimeshort', 'langconfig'));
  60. }
  61. if (empty($file['isdir'])) {
  62. if ($file['filesize']) {
  63. $filesize = display_size($file['filesize']);
  64. }
  65. $fileicon = file_file_icon($file, 24);
  66. $filetype = get_mimetype_description($file);
  67. } else {
  68. $fileicon = file_folder_icon(24);
  69. }
  70. $table->data[] = array(
  71. html_writer::link($file['url'], $this->output->pix_icon($fileicon, get_string('icon')) . ' ' . $file['filename']),
  72. $filedate,
  73. $filesize,
  74. $filetype
  75. );
  76. }
  77. $html .= html_writer::table($table);
  78. $html .= $this->output->single_button(new moodle_url('/files/coursefilesedit.php', array('contextid'=>$tree->context->id)), get_string('coursefilesedit'), 'get');
  79. $html .= $this->output->box_end();
  80. return $html;
  81. }
  82. /**
  83. * Prints the file manager and initializes all necessary libraries
  84. *
  85. * <pre>
  86. * $fm = new form_filemanager($options);
  87. * $output = get_renderer('core', 'files');
  88. * echo $output->render($fm);
  89. * </pre>
  90. *
  91. * @param form_filemanager $fm File manager to render
  92. * @return string HTML fragment
  93. */
  94. public function render_form_filemanager($fm) {
  95. $html = $this->fm_print_generallayout($fm);
  96. $module = array(
  97. 'name'=>'form_filemanager',
  98. 'fullpath'=>'/lib/form/filemanager.js',
  99. 'requires' => array('moodle-core-notification-dialogue', 'core_filepicker', 'base', 'io-base', 'node', 'json', 'core_dndupload', 'panel', 'resize-plugin', 'dd-plugin'),
  100. 'strings' => array(
  101. array('error', 'moodle'), array('info', 'moodle'), array('confirmdeletefile', 'repository'),
  102. array('draftareanofiles', 'repository'), array('entername', 'repository'), array('enternewname', 'repository'),
  103. array('invalidjson', 'repository'), array('popupblockeddownload', 'repository'),
  104. array('unknownoriginal', 'repository'), array('confirmdeletefolder', 'repository'),
  105. array('confirmdeletefilewithhref', 'repository'), array('confirmrenamefolder', 'repository'),
  106. array('confirmrenamefile', 'repository'), array('newfolder', 'repository'), array('edit', 'moodle')
  107. )
  108. );
  109. if ($this->page->requires->should_create_one_time_item_now('core_file_managertemplate')) {
  110. $this->page->requires->js_init_call('M.form_filemanager.set_templates',
  111. array($this->filemanager_js_templates()), true, $module);
  112. }
  113. $this->page->requires->js_init_call('M.form_filemanager.init', array($fm->options), true, $module);
  114. // non javascript file manager
  115. $html .= '<noscript>';
  116. $html .= "<div><object type='text/html' data='".$fm->get_nonjsurl()."' height='160' width='600' style='border:1px solid #000'></object></div>";
  117. $html .= '</noscript>';
  118. return $html;
  119. }
  120. /**
  121. * Returns html for displaying one file manager
  122. *
  123. * The main element in HTML must have id="filemanager-{$client_id}" and
  124. * class="filemanager fm-loading";
  125. * After all necessary code on the page (both html and javascript) is loaded,
  126. * the class fm-loading will be removed and added class fm-loaded;
  127. * The main element (class=filemanager) will be assigned the following classes:
  128. * 'fm-maxfiles' - when filemanager has maximum allowed number of files;
  129. * 'fm-nofiles' - when filemanager has no files at all (although there might be folders);
  130. * 'fm-noitems' - when current view (folder) has no items - neither files nor folders;
  131. * 'fm-updating' - when current view is being updated (usually means that loading icon is to be displayed);
  132. * 'fm-nomkdir' - when 'Make folder' action is unavailable (empty($fm->options->subdirs) == true)
  133. *
  134. * Element with class 'filemanager-container' will be holding evens for dnd upload (dragover, etc.).
  135. * It will have class:
  136. * 'dndupload-ready' - when a file is being dragged over the browser
  137. * 'dndupload-over' - when file is being dragged over this filepicker (additional to 'dndupload-ready')
  138. * 'dndupload-uploading' - during the upload process (note that after dnd upload process is
  139. * over, the file manager will refresh the files list and therefore will have for a while class
  140. * fm-updating. Both waiting processes should look similar so the images don't jump for user)
  141. *
  142. * If browser supports Drag-and-drop, the body element will have class 'dndsupported',
  143. * otherwise - 'dndnotsupported';
  144. *
  145. * Element with class 'fp-content' will be populated with files list;
  146. * Element with class 'fp-btn-add' will hold onclick event for adding a file (opening filepicker);
  147. * Element with class 'fp-btn-mkdir' will hold onclick event for adding new folder;
  148. * Element with class 'fp-btn-download' will hold onclick event for download action;
  149. *
  150. * Element with class 'fp-path-folder' is a template for one folder in path toolbar.
  151. * It will hold mouse click event and will be assigned classes first/last/even/odd respectfully.
  152. * Parent element will receive class 'empty' when there are no folders to be displayed;
  153. * The content of subelement with class 'fp-path-folder-name' will be substituted with folder name;
  154. *
  155. * Element with class 'fp-viewbar' will have the class 'enabled' or 'disabled' when view mode
  156. * can be changed or not;
  157. * Inside element with class 'fp-viewbar' there are expected elements with classes
  158. * 'fp-vb-icons', 'fp-vb-tree' and 'fp-vb-details'. They will handle onclick events to switch
  159. * between the view modes, the last clicked element will have the class 'checked';
  160. *
  161. * @param form_filemanager $fm
  162. * @return string
  163. */
  164. private function fm_print_generallayout($fm) {
  165. global $OUTPUT;
  166. $options = $fm->options;
  167. $client_id = $options->client_id;
  168. $straddfile = get_string('addfile', 'repository');
  169. $strmakedir = get_string('makeafolder', 'moodle');
  170. $strdownload = get_string('downloadfolder', 'repository');
  171. $strloading = get_string('loading', 'repository');
  172. $strdroptoupload = get_string('droptoupload', 'moodle');
  173. $icon_progress = $OUTPUT->pix_icon('i/loading_small', $strloading).'';
  174. $restrictions = $this->fm_print_restrictions($fm);
  175. $strdndnotsupported = get_string('dndnotsupported_insentence', 'moodle').$OUTPUT->help_icon('dndnotsupported');
  176. $strdndenabledinbox = get_string('dndenabled_inbox', 'moodle');
  177. $loading = get_string('loading', 'repository');
  178. $straddfiletext = get_string('addfiletext', 'repository');
  179. $strcreatefolder = get_string('createfolder', 'repository');
  180. $strdownloadallfiles = get_string('downloadallfiles', 'repository');
  181. $html = '
  182. <div id="filemanager-'.$client_id.'" class="filemanager fm-loading">
  183. <div class="fp-restrictions">
  184. '.$restrictions.'
  185. <span class="dnduploadnotsupported-message"> - '.$strdndnotsupported.' </span>
  186. </div>
  187. <div class="fp-navbar">
  188. <div class="filemanager-toolbar">
  189. <div class="fp-toolbar">
  190. <div class="fp-btn-add">
  191. <a role="button" title="' . $straddfile . '" href="#">
  192. <img src="' . $this->pix_url('a/add_file') . '" alt="' . $straddfiletext . '" />
  193. </a>
  194. </div>
  195. <div class="fp-btn-mkdir">
  196. <a role="button" title="' . $strmakedir . '" href="#">
  197. <img src="' . $this->pix_url('a/create_folder') . '" alt="' . $strcreatefolder . '" />
  198. </a>
  199. </div>
  200. <div class="fp-btn-download">
  201. <a role="button" title="' . $strdownload . '" href="#">
  202. <img src="' . $this->pix_url('a/download_all').'" alt="' . $strdownloadallfiles . '" />
  203. </a>
  204. </div>
  205. <img class="fp-img-downloading" src="'.$this->pix_url('i/loading_small').'" alt="" />
  206. </div>
  207. <div class="fp-viewbar">
  208. <a title="'. get_string('displayicons', 'repository') .'" class="fp-vb-icons" href="#">
  209. <img alt="'. get_string('displayasicons', 'repository') .'" src="'. $this->pix_url('fp/view_icon_active', 'theme') .'" />
  210. </a>
  211. <a title="'. get_string('displaydetails', 'repository') .'" class="fp-vb-details" href="#">
  212. <img alt="'. get_string('displayasdetails', 'repository') .'" src="'. $this->pix_url('fp/view_list_active', 'theme') .'" />
  213. </a>
  214. <a title="'. get_string('displaytree', 'repository') .'" class="fp-vb-tree" href="#">
  215. <img alt="'. get_string('displayastree', 'repository') .'" src="'. $this->pix_url('fp/view_tree_active', 'theme') .'" />
  216. </a>
  217. </div>
  218. </div>
  219. <div class="fp-pathbar">
  220. <span class="fp-path-folder"><a class="fp-path-folder-name" href="#"></a></span>
  221. </div>
  222. </div>
  223. <div class="filemanager-loading mdl-align">'.$icon_progress.'</div>
  224. <div class="filemanager-container" >
  225. <div class="fm-content-wrapper">
  226. <div class="fp-content"></div>
  227. <div class="fm-empty-container">
  228. <div class="dndupload-message">'.$strdndenabledinbox.'<br/><div class="dndupload-arrow"></div></div>
  229. </div>
  230. <div class="dndupload-target">'.$strdroptoupload.'<br/><div class="dndupload-arrow"></div></div>
  231. <div class="dndupload-progressbars"></div>
  232. <div class="dndupload-uploadinprogress">'.$icon_progress.'</div>
  233. </div>
  234. <div class="filemanager-updating">'.$icon_progress.'</div>
  235. </div>
  236. </div>';
  237. return $html;
  238. }
  239. /**
  240. * FileManager JS template for displaying one file in 'icon view' mode.
  241. *
  242. * Except for elements described in fp_js_template_iconfilename, this template may also
  243. * contain element with class 'fp-contextmenu'. If context menu is available for this
  244. * file, the top element will receive the additional class 'fp-hascontextmenu' and
  245. * the element with class 'fp-contextmenu' will hold onclick event for displaying
  246. * the context menu.
  247. *
  248. * @see fp_js_template_iconfilename()
  249. * @return string
  250. */
  251. private function fm_js_template_iconfilename() {
  252. $rv = '
  253. <div class="fp-file">
  254. <a href="#">
  255. <div style="position:relative;">
  256. <div class="fp-thumbnail"></div>
  257. <div class="fp-reficons1"></div>
  258. <div class="fp-reficons2"></div>
  259. </div>
  260. <div class="fp-filename-field">
  261. <div class="fp-filename"></div>
  262. </div>
  263. </a>
  264. <a class="fp-contextmenu" href="#">'.$this->pix_icon('i/menu', '▶').'</a>
  265. </div>';
  266. return $rv;
  267. }
  268. /**
  269. * FileManager JS template for displaying file name in 'table view' and 'tree view' modes.
  270. *
  271. * Except for elements described in fp_js_template_listfilename, this template may also
  272. * contain element with class 'fp-contextmenu'. If context menu is available for this
  273. * file, the top element will receive the additional class 'fp-hascontextmenu' and
  274. * the element with class 'fp-contextmenu' will hold onclick event for displaying
  275. * the context menu.
  276. *
  277. * @todo MDL-32736 remove onclick="return false;"
  278. * @see fp_js_template_listfilename()
  279. * @return string
  280. */
  281. private function fm_js_template_listfilename() {
  282. $rv = '
  283. <span class="fp-filename-icon">
  284. <a href="#">
  285. <span class="fp-icon"></span>
  286. <span class="fp-reficons1"></span>
  287. <span class="fp-reficons2"></span>
  288. <span class="fp-filename"></span>
  289. </a>
  290. <a class="fp-contextmenu" href="#" onclick="return false;">'.$this->pix_icon('i/menu', '▶').'</a>
  291. </span>';
  292. return $rv;
  293. }
  294. /**
  295. * FileManager JS template for displaying 'Make new folder' dialog.
  296. *
  297. * Must be wrapped in an element, CSS for this element must define width and height of the window;
  298. *
  299. * Must have one input element with type="text" (for users to enter the new folder name);
  300. *
  301. * content of element with class 'fp-dlg-curpath' will be replaced with current path where
  302. * new folder is about to be created;
  303. * elements with classes 'fp-dlg-butcreate' and 'fp-dlg-butcancel' will hold onclick events;
  304. *
  305. * @return string
  306. */
  307. private function fm_js_template_mkdir() {
  308. $rv = '
  309. <div class="filemanager fp-mkdir-dlg" role="dialog" aria-live="assertive" aria-labelledby="fp-mkdir-dlg-title">
  310. <div class="fp-mkdir-dlg-text">
  311. <label id="fp-mkdir-dlg-title">' . get_string('newfoldername', 'repository') . '</label><br/>
  312. <input type="text" />
  313. </div>
  314. <button class="fp-dlg-butcreate btn-primary btn">'.get_string('makeafolder').'</button>
  315. <button class="fp-dlg-butcancel btn-cancel btn">'.get_string('cancel').'</button>
  316. </div>';
  317. return $rv;
  318. }
  319. /**
  320. * FileManager JS template for error/info message displayed as a separate popup window.
  321. *
  322. * @see fp_js_template_message()
  323. * @return string
  324. */
  325. private function fm_js_template_message() {
  326. return $this->fp_js_template_message();
  327. }
  328. /**
  329. * FileManager JS template for window with file information/actions.
  330. *
  331. * All content must be enclosed in one element, CSS for this class must define width and
  332. * height of the window;
  333. *
  334. * Thumbnail image will be added as content to the element with class 'fp-thumbnail';
  335. *
  336. * Inside the window the elements with the following classnames must be present:
  337. * 'fp-saveas', 'fp-author', 'fp-license', 'fp-path'. Inside each of them must be
  338. * one input element (or select in case of fp-license and fp-path). They may also have labels.
  339. * The elements will be assign with class 'uneditable' and input/select element will become
  340. * disabled if they are not applicable for the particular file;
  341. *
  342. * There may be present elements with classes 'fp-original', 'fp-datemodified', 'fp-datecreated',
  343. * 'fp-size', 'fp-dimensions', 'fp-reflist'. They will receive additional class 'fp-unknown' if
  344. * information is unavailable. If there is information available, the content of embedded
  345. * element with class 'fp-value' will be substituted with the value;
  346. *
  347. * The value of Original ('fp-original') is loaded in separate request. When it is applicable
  348. * but not yet loaded the 'fp-original' element receives additional class 'fp-loading';
  349. *
  350. * The value of 'Aliases/Shortcuts' ('fp-reflist') is also loaded in separate request. When it
  351. * is applicable but not yet loaded the 'fp-original' element receives additional class
  352. * 'fp-loading'. The string explaining that XX references exist will replace content of element
  353. * 'fp-refcount'. Inside '.fp-reflist .fp-value' each reference will be enclosed in <li>;
  354. *
  355. * Elements with classes 'fp-file-update', 'fp-file-download', 'fp-file-delete', 'fp-file-zip',
  356. * 'fp-file-unzip', 'fp-file-setmain' and 'fp-file-cancel' will hold corresponding onclick
  357. * events (there may be several elements with class 'fp-file-cancel');
  358. *
  359. * When confirm button is pressed and file is being selected, the top element receives
  360. * additional class 'loading'. It is removed when response from server is received.
  361. *
  362. * When any of the input fields is changed, the top element receives class 'fp-changed';
  363. * When current file can be set as main - top element receives class 'fp-cansetmain';
  364. * When current file is folder/zip/file - top element receives respectfully class
  365. * 'fp-folder'/'fp-zip'/'fp-file';
  366. *
  367. * @return string
  368. */
  369. private function fm_js_template_fileselectlayout() {
  370. global $OUTPUT;
  371. $strloading = get_string('loading', 'repository');
  372. $iconprogress = $this->pix_icon('i/loading_small', $strloading).'';
  373. $rv = '
  374. <div class="filemanager fp-select">
  375. <div class="fp-select-loading">
  376. <img src="'.$this->pix_url('i/loading_small').'" />
  377. </div>
  378. <form class="form-horizontal">
  379. <button class="fp-file-download">'.get_string('download').'</button>
  380. <button class="fp-file-delete">'.get_string('delete').'</button>
  381. <button class="fp-file-setmain">'.get_string('setmainfile', 'repository').'</button>
  382. <span class="fp-file-setmain-help">'.$OUTPUT->help_icon('setmainfile', 'repository').'</span>
  383. <button class="fp-file-zip">'.get_string('zip', 'editor').'</button>
  384. <button class="fp-file-unzip">'.get_string('unzip').'</button>
  385. <div class="fp-hr"></div>
  386. <div class="fp-forminset">
  387. <div class="fp-saveas control-group clearfix">
  388. <label class="control-label">'.get_string('name', 'repository').'</label>
  389. <div class="controls">
  390. <input type="text"/>
  391. </div>
  392. </div>
  393. <div class="fp-author control-group clearfix">
  394. <label class="control-label">'.get_string('author', 'repository').'</label>
  395. <div class="controls">
  396. <input type="text"/>
  397. </div>
  398. </div>
  399. <div class="fp-license control-group clearfix">
  400. <label class="control-label">'.get_string('chooselicense', 'repository').'</label>
  401. <div class="controls">
  402. <select></select>
  403. </div>
  404. </div>
  405. <div class="fp-path control-group clearfix">
  406. <label class="control-label">'.get_string('path', 'repository').'</label>
  407. <div class="controls">
  408. <select></select>
  409. </div>
  410. </div>
  411. <div class="fp-original control-group clearfix">
  412. <label class="control-label">'.get_string('original', 'repository').'</label>
  413. <div class="controls">
  414. <span class="fp-originloading">'.$iconprogress.' '.$strloading.'</span><span class="fp-value"></span>
  415. </div>
  416. </div>
  417. <div class="fp-reflist control-group clearfix">
  418. <label class="control-label">'.get_string('referenceslist', 'repository').'</label>
  419. <div class="controls">
  420. <p class="fp-refcount"></p>
  421. <span class="fp-reflistloading">'.$iconprogress.' '.$strloading.'</span>
  422. <ul class="fp-value"></ul>
  423. </div>
  424. </div>
  425. </div>
  426. <div class="fp-select-buttons">
  427. <button class="fp-file-update btn-primary btn">'.get_string('update', 'moodle').'</button>
  428. <button class="fp-file-cancel btn-cancel btn">'.get_string('cancel').'</button>
  429. </div>
  430. </form>
  431. <div class="fp-info clearfix">
  432. <div class="fp-hr"></div>
  433. <p class="fp-thumbnail"></p>
  434. <div class="fp-fileinfo">
  435. <div class="fp-datemodified">'.get_string('lastmodified', 'repository').' <span class="fp-value"></span></div>
  436. <div class="fp-datecreated">'.get_string('datecreated', 'repository').' <span class="fp-value"></span></div>
  437. <div class="fp-size">'.get_string('size', 'repository').' <span class="fp-value"></span></div>
  438. <div class="fp-dimensions">'.get_string('dimensions', 'repository').' <span class="fp-value"></span></div>
  439. </div>
  440. </div>
  441. </div>';
  442. return $rv;
  443. }
  444. /**
  445. * FileManager JS template for popup confirm dialogue window.
  446. *
  447. * Must have one top element, CSS for this element must define width and height of the window;
  448. *
  449. * content of element with class 'fp-dlg-text' will be replaced with dialog text;
  450. * elements with classes 'fp-dlg-butconfirm' and 'fp-dlg-butcancel' will
  451. * hold onclick events;
  452. *
  453. * @return string
  454. */
  455. private function fm_js_template_confirmdialog() {
  456. $rv = '
  457. <div class="filemanager fp-dlg">
  458. <div class="fp-dlg-text"></div>
  459. <button class="fp-dlg-butconfirm btn-primary btn">'.get_string('ok').'</button>
  460. <button class="fp-dlg-butcancel btn-cancel btn">'.get_string('cancel').'</button>
  461. </div>';
  462. return $rv;
  463. }
  464. /**
  465. * Returns all FileManager JavaScript templates as an array.
  466. *
  467. * @return array
  468. */
  469. public function filemanager_js_templates() {
  470. $class_methods = get_class_methods($this);
  471. $templates = array();
  472. foreach ($class_methods as $method_name) {
  473. if (preg_match('/^fm_js_template_(.*)$/', $method_name, $matches))
  474. $templates[$matches[1]] = $this->$method_name();
  475. }
  476. return $templates;
  477. }
  478. /**
  479. * Displays restrictions for the file manager
  480. *
  481. * @param form_filemanager $fm
  482. * @return string
  483. */
  484. private function fm_print_restrictions($fm) {
  485. $maxbytes = display_size($fm->options->maxbytes);
  486. $strparam = (object) array('size' => $maxbytes, 'attachments' => $fm->options->maxfiles,
  487. 'areasize' => display_size($fm->options->areamaxbytes));
  488. $hasmaxfiles = !empty($fm->options->maxfiles) && $fm->options->maxfiles > 0;
  489. $hasarealimit = !empty($fm->options->areamaxbytes) && $fm->options->areamaxbytes != -1;
  490. if ($hasmaxfiles && $hasarealimit) {
  491. $maxsize = get_string('maxsizeandattachmentsandareasize', 'moodle', $strparam);
  492. } else if ($hasmaxfiles) {
  493. $maxsize = get_string('maxsizeandattachments', 'moodle', $strparam);
  494. } else if ($hasarealimit) {
  495. $maxsize = get_string('maxsizeandareasize', 'moodle', $strparam);
  496. } else {
  497. $maxsize = get_string('maxfilesize', 'moodle', $maxbytes);
  498. }
  499. // TODO MDL-32020 also should say about 'File types accepted'
  500. return '<span>'. $maxsize . '</span>';
  501. }
  502. /**
  503. * Template for FilePicker with general layout (not QuickUpload).
  504. *
  505. * Must have one top element containing everything else (recommended <div class="file-picker">),
  506. * CSS for this element must define width and height of the filepicker window. Or CSS must
  507. * define min-width, max-width, min-height and max-height and in this case the filepicker
  508. * window will be resizeable;
  509. *
  510. * Element with class 'fp-viewbar' will have the class 'enabled' or 'disabled' when view mode
  511. * can be changed or not;
  512. * Inside element with class 'fp-viewbar' there are expected elements with classes
  513. * 'fp-vb-icons', 'fp-vb-tree' and 'fp-vb-details'. They will handle onclick events to switch
  514. * between the view modes, the last clicked element will have the class 'checked';
  515. *
  516. * Element with class 'fp-repo' is a template for displaying one repository. Other repositories
  517. * will be attached as siblings (classes first/last/even/odd will be added respectfully).
  518. * The currently selected repostory will have class 'active'. Contents of element with class
  519. * 'fp-repo-name' will be replaced with repository name, source of image with class
  520. * 'fp-repo-icon' will be replaced with repository icon;
  521. *
  522. * Element with class 'fp-content' is obligatory and will hold the current contents;
  523. *
  524. * Element with class 'fp-paging' will contain page navigation (will be deprecated soon);
  525. *
  526. * Element with class 'fp-path-folder' is a template for one folder in path toolbar.
  527. * It will hold mouse click event and will be assigned classes first/last/even/odd respectfully.
  528. * Parent element will receive class 'empty' when there are no folders to be displayed;
  529. * The content of subelement with class 'fp-path-folder-name' will be substituted with folder name;
  530. *
  531. * Element with class 'fp-toolbar' will have class 'empty' if all 'Back', 'Search', 'Refresh',
  532. * 'Logout', 'Manage' and 'Help' are unavailable for this repo;
  533. *
  534. * Inside fp-toolbar there are expected elements with classes fp-tb-back, fp-tb-search,
  535. * fp-tb-refresh, fp-tb-logout, fp-tb-manage and fp-tb-help. Each of them will have
  536. * class 'enabled' or 'disabled' if particular repository has this functionality.
  537. * Element with class 'fp-tb-search' must contain empty form inside, it's contents will
  538. * be substituted with the search form returned by repository (in the most cases it
  539. * is generated with template core_repository_renderer::repository_default_searchform);
  540. * Other elements must have either <a> or <button> element inside, it will hold onclick
  541. * event for corresponding action; labels for fp-tb-back and fp-tb-logout may be
  542. * replaced with those specified by repository;
  543. *
  544. * @return string
  545. */
  546. private function fp_js_template_generallayout() {
  547. $rv = '
  548. <div tabindex="0" class="file-picker fp-generallayout" role="dialog" aria-live="assertive">
  549. <div class="fp-repo-area">
  550. <ul class="fp-list">
  551. <li class="fp-repo">
  552. <a href="#"><img class="fp-repo-icon" alt=" " width="16" height="16" />&nbsp;<span class="fp-repo-name"></span></a>
  553. </li>
  554. </ul>
  555. </div>
  556. <div class="fp-repo-items" tabindex="0">
  557. <div class="fp-navbar">
  558. <div>
  559. <div class="fp-toolbar">
  560. <div class="fp-tb-back">
  561. <a href="#">'.get_string('back', 'repository').'</a>
  562. </div>
  563. <div class="fp-tb-search">
  564. <form></form>
  565. </div>
  566. <div class="fp-tb-refresh">
  567. <a title="'. get_string('refresh', 'repository') .'" href="#">
  568. <img alt="" src="'.$this->pix_url('a/refresh').'" />
  569. </a>
  570. </div>
  571. <div class="fp-tb-logout">
  572. <a title="'. get_string('logout', 'repository') .'" href="#">
  573. <img alt="" src="'.$this->pix_url('a/logout').'" />
  574. </a>
  575. </div>
  576. <div class="fp-tb-manage">
  577. <a title="'. get_string('settings', 'repository') .'" href="#">
  578. <img alt="" src="'.$this->pix_url('a/setting').'" />
  579. </a>
  580. </div>
  581. <div class="fp-tb-help">
  582. <a title="'. get_string('help', 'repository') .'" href="#">
  583. <img alt="" src="'.$this->pix_url('a/help').'" />
  584. </a>
  585. </div>
  586. <div class="fp-tb-message"></div>
  587. </div>
  588. <div class="fp-viewbar">
  589. <a role="button" title="'. get_string('displayicons', 'repository') .'" class="fp-vb-icons" href="#">
  590. <img alt="" src="'. $this->pix_url('fp/view_icon_active', 'theme') .'" />
  591. </a>
  592. <a role="button" title="'. get_string('displaydetails', 'repository') .'" class="fp-vb-details" href="#">
  593. <img alt="" src="'. $this->pix_url('fp/view_list_active', 'theme') .'" />
  594. </a>
  595. <a role="button" title="'. get_string('displaytree', 'repository') .'" class="fp-vb-tree" href="#">
  596. <img alt="" src="'. $this->pix_url('fp/view_tree_active', 'theme') .'" />
  597. </a>
  598. </div>
  599. <div class="fp-clear-left"></div>
  600. </div>
  601. <div class="fp-pathbar">
  602. <span class="fp-path-folder"><a class="fp-path-folder-name" href="#"></a></span>
  603. </div>
  604. </div>
  605. <div class="fp-content"></div>
  606. </div>
  607. </div>';
  608. return $rv;
  609. }
  610. /**
  611. * FilePicker JS template for displaying one file in 'icon view' mode.
  612. *
  613. * the element with class 'fp-thumbnail' will be resized to the repository thumbnail size
  614. * (both width and height, unless min-width and/or min-height is set in CSS) and the content of
  615. * an element will be replaced with an appropriate img;
  616. *
  617. * the width of element with class 'fp-filename' will be set to the repository thumbnail width
  618. * (unless min-width is set in css) and the content of an element will be replaced with filename
  619. * supplied by repository;
  620. *
  621. * top element(s) will have class fp-folder if the element is a folder;
  622. *
  623. * List of files will have parent <div> element with class 'fp-iconview'
  624. *
  625. * @return string
  626. */
  627. private function fp_js_template_iconfilename() {
  628. $rv = '
  629. <a class="fp-file" href="#" >
  630. <div style="position:relative;">
  631. <div class="fp-thumbnail"></div>
  632. <div class="fp-reficons1"></div>
  633. <div class="fp-reficons2"></div>
  634. </div>
  635. <div class="fp-filename-field">
  636. <p class="fp-filename"></p>
  637. </div>
  638. </a>';
  639. return $rv;
  640. }
  641. /**
  642. * FilePicker JS template for displaying file name in 'table view' and 'tree view' modes.
  643. *
  644. * content of the element with class 'fp-icon' will be replaced with an appropriate img;
  645. *
  646. * content of element with class 'fp-filename' will be replaced with filename supplied by
  647. * repository;
  648. *
  649. * top element(s) will have class fp-folder if the element is a folder;
  650. *
  651. * Note that tree view and table view are the YUI widgets and therefore there are no
  652. * other templates. The widgets will be wrapped in <div> with class fp-treeview or
  653. * fp-tableview (respectfully).
  654. *
  655. * @return string
  656. */
  657. private function fp_js_template_listfilename() {
  658. $rv = '
  659. <span class="fp-filename-icon">
  660. <a href="#">
  661. <span class="fp-icon"></span>
  662. <span class="fp-filename"></span>
  663. </a>
  664. </span>';
  665. return $rv;
  666. }
  667. /**
  668. * FilePicker JS template for displaying link/loading progress for fetching of the next page
  669. *
  670. * This text is added to .fp-content AFTER .fp-iconview/.fp-treeview/.fp-tableview
  671. *
  672. * Must have one parent element with class 'fp-nextpage'. It will be assigned additional
  673. * class 'loading' during loading of the next page (it is recommended that in this case the link
  674. * becomes unavailable). Also must contain one element <a> or <button> that will hold
  675. * onclick event for displaying of the next page. The event will be triggered automatically
  676. * when user scrolls to this link.
  677. *
  678. * @return string
  679. */
  680. private function fp_js_template_nextpage() {
  681. $rv = '
  682. <div class="fp-nextpage">
  683. <div class="fp-nextpage-link"><a href="#">'.get_string('more').'</a></div>
  684. <div class="fp-nextpage-loading">
  685. <img src="'.$this->pix_url('i/loading_small').'" />
  686. </div>
  687. </div>';
  688. return $rv;
  689. }
  690. /**
  691. * FilePicker JS template for window appearing to select a file.
  692. *
  693. * All content must be enclosed in one element, CSS for this class must define width and
  694. * height of the window;
  695. *
  696. * Thumbnail image will be added as content to the element with class 'fp-thumbnail';
  697. *
  698. * Inside the window the elements with the following classnames must be present:
  699. * 'fp-saveas', 'fp-linktype-2', 'fp-linktype-1', 'fp-linktype-4', 'fp-setauthor',
  700. * 'fp-setlicense'. Inside each of them must have one input element (or select in case of
  701. * fp-setlicense). They may also have labels.
  702. * The elements will be assign with class 'uneditable' and input/select element will become
  703. * disabled if they are not applicable for the particular file;
  704. *
  705. * There may be present elements with classes 'fp-datemodified', 'fp-datecreated', 'fp-size',
  706. * 'fp-license', 'fp-author', 'fp-dimensions'. They will receive additional class 'fp-unknown'
  707. * if information is unavailable. If there is information available, the content of embedded
  708. * element with class 'fp-value' will be substituted with the value;
  709. *
  710. * Elements with classes 'fp-select-confirm' and 'fp-select-cancel' will hold corresponding
  711. * onclick events;
  712. *
  713. * When confirm button is pressed and file is being selected, the top element receives
  714. * additional class 'loading'. It is removed when response from server is received.
  715. *
  716. * @return string
  717. */
  718. private function fp_js_template_selectlayout() {
  719. $rv = '
  720. <div class="file-picker fp-select">
  721. <div class="fp-select-loading">
  722. <img src="'.$this->pix_url('i/loading_small').'" />
  723. </div>
  724. <form class="form-horizontal">
  725. <div class="fp-forminset">
  726. <div class="fp-linktype-2 control-group control-radio clearfix">
  727. <label class="control-label control-radio">'.get_string('makefileinternal', 'repository').'</label>
  728. <div class="controls control-radio">
  729. <input type="radio"/>
  730. </div>
  731. </div>
  732. <div class="fp-linktype-1 control-group control-radio clearfix">
  733. <label class="control-label control-radio">'.get_string('makefilelink', 'repository').'</label>
  734. <div class="controls control-radio">
  735. <input type="radio"/>
  736. </div>
  737. </div>
  738. <div class="fp-linktype-4 control-group control-radio clearfix">
  739. <label class="control-label control-radio">'.get_string('makefilereference', 'repository').'</label>
  740. <div class="controls control-radio">
  741. <input type="radio"/>
  742. </div>
  743. </div>
  744. <div class="fp-saveas control-group clearfix">
  745. <label class="control-label">'.get_string('saveas', 'repository').'</label>
  746. <div class="controls">
  747. <input type="text"/>
  748. </div>
  749. </div>
  750. <div class="fp-setauthor control-group clearfix">
  751. <label class="control-label">'.get_string('author', 'repository').'</label>
  752. <div class="controls">
  753. <input type="text"/>
  754. </div>
  755. </div>
  756. <div class="fp-setlicense control-group clearfix">
  757. <label class="control-label">'.get_string('chooselicense', 'repository').'</label>
  758. <div class="controls">
  759. <select></select>
  760. </div>
  761. </div>
  762. </div>
  763. <div class="fp-select-buttons">
  764. <button class="fp-select-confirm btn-primary btn">'.get_string('getfile', 'repository').'</button>
  765. <button class="fp-select-cancel btn-cancel btn">'.get_string('cancel').'</button>
  766. </div>
  767. </form>
  768. <div class="fp-info clearfix">
  769. <div class="fp-hr"></div>
  770. <p class="fp-thumbnail"></p>
  771. <div class="fp-fileinfo">
  772. <div class="fp-datemodified">'.get_string('lastmodified', 'repository').'<span class="fp-value"></span></div>
  773. <div class="fp-datecreated">'.get_string('datecreated', 'repository').'<span class="fp-value"></span></div>
  774. <div class="fp-size">'.get_string('size', 'repository').'<span class="fp-value"></span></div>
  775. <div class="fp-license">'.get_string('license', 'repository').'<span class="fp-value"></span></div>
  776. <div class="fp-author">'.get_string('author', 'repository').'<span class="fp-value"></span></div>
  777. <div class="fp-dimensions">'.get_string('dimensions', 'repository').'<span class="fp-value"></span></div>
  778. </div>
  779. </div>
  780. </div>';
  781. return $rv;
  782. }
  783. /**
  784. * FilePicker JS template for 'Upload file' repository
  785. *
  786. * Content to display when user chooses 'Upload file' repository (will be nested inside
  787. * element with class 'fp-content').
  788. *
  789. * Must contain form (enctype="multipart/form-data" method="POST")
  790. *
  791. * The elements with the following classnames must be present:
  792. * 'fp-file', 'fp-saveas', 'fp-setauthor', 'fp-setlicense'. Inside each of them must have
  793. * one input element (or select in case of fp-setlicense). They may also have labels.
  794. *
  795. * Element with class 'fp-upload-btn' will hold onclick event for uploading the file;
  796. *
  797. * Please note that some fields may be hidden using CSS if this is part of quickupload form
  798. *
  799. * @return string
  800. */
  801. private function fp_js_template_uploadform() {
  802. $rv = '
  803. <div class="fp-upload-form">
  804. <div class="fp-content-center">
  805. <form enctype="multipart/form-data" method="POST" class="form-horizontal">
  806. <div class="fp-formset">
  807. <div class="fp-file control-group clearfix">
  808. <label class="control-label">'.get_string('attachment', 'repository').'</label>
  809. <div class="controls">
  810. <input type="file"/>
  811. </div>
  812. </div>
  813. <div class="fp-saveas control-group clearfix">
  814. <label class="control-label">'.get_string('saveas', 'repository').'</label>
  815. <div class="controls">
  816. <input type="text"/>
  817. </div>
  818. </div>
  819. <div class="fp-setauthor control-group clearfix">
  820. <label class="control-label">'.get_string('author', 'repository').'</label>
  821. <div class="controls">
  822. <input type="text"/>
  823. </div>
  824. </div>
  825. <div class="fp-setlicense control-group clearfix">
  826. <label class="control-label">'.get_string('chooselicense', 'repository').'</label>
  827. <div class="controls">
  828. <select ></select>
  829. </div>
  830. </div>
  831. </div>
  832. </form>
  833. <div class="mdl-align">
  834. <button class="fp-upload-btn btn-primary btn">'.get_string('upload', 'repository').'</button>
  835. </div>
  836. </div>
  837. </div> ';
  838. return $rv;
  839. }
  840. /**
  841. * FilePicker JS template to display during loading process (inside element with class 'fp-content').
  842. *
  843. * @return string
  844. */
  845. private function fp_js_template_loading() {
  846. return '
  847. <div class="fp-content-loading">
  848. <div class="fp-content-center">
  849. <img src="'.$this->pix_url('i/loading_small').'" />
  850. </div>
  851. </div>';
  852. }
  853. /**
  854. * FilePicker JS template for error (inside element with class 'fp-content').
  855. *
  856. * must have element with class 'fp-error', its content will be replaced with error text
  857. * and the error code will be assigned as additional class to this element
  858. * used errors: invalidjson, nofilesavailable, norepositoriesavailable
  859. *
  860. * @return string
  861. */
  862. private function fp_js_template_error() {
  863. $rv = '
  864. <div class="fp-content-error" ><div class="fp-error"></div></div>';
  865. return $rv;
  866. }
  867. /**
  868. * FilePicker JS template for error/info message displayed as a separate popup window.
  869. *
  870. * Must be wrapped in one element, CSS for this element must define
  871. * width and height of the window. It will be assigned with an additional class 'fp-msg-error'
  872. * or 'fp-msg-info' depending on message type;
  873. *
  874. * content of element with class 'fp-msg-text' will be replaced with error/info text;
  875. *
  876. * element with class 'fp-msg-butok' will hold onclick event
  877. *
  878. * @return string
  879. */
  880. private function fp_js_template_message() {
  881. $rv = '
  882. <div class="file-picker fp-msg" role="alertdialog" aria-live="assertive" aria-labelledby="fp-msg-labelledby">
  883. <p class="fp-msg-text" id="fp-msg-labelledby"></p>
  884. <button class="fp-msg-butok btn-primary btn">'.get_string('ok').'</button>
  885. </div>';
  886. return $rv;
  887. }
  888. /**
  889. * FilePicker JS template for popup dialogue window asking for action when file with the same name already exists.
  890. *
  891. * Must have one top element, CSS for this element must define width and height of the window;
  892. *
  893. * content of element with class 'fp-dlg-text' will be replaced with dialog text;
  894. * elements with classes 'fp-dlg-butoverwrite', 'fp-dlg-butrename',
  895. * 'fp-dlg-butoverwriteall', 'fp-dlg-butrenameall' and 'fp-dlg-butcancel' will
  896. * hold onclick events;
  897. *
  898. * content of element with class 'fp-dlg-butrename' will be substituted with appropriate string
  899. * (Note that it may have long text)
  900. *
  901. * @return string
  902. */
  903. private function fp_js_template_processexistingfile() {
  904. $rv = '
  905. <div class="file-picker fp-dlg">
  906. <p class="fp-dlg-text"></p>
  907. <div class="fp-dlg-buttons">
  908. <button class="fp-dlg-butoverwrite btn">'.get_string('overwrite', 'repository').'</button>
  909. <button class="fp-dlg-butrename btn"></button>
  910. <button class="fp-dlg-butcancel btn btn-cancel">'.get_string('cancel').'</button>
  911. </div>
  912. </div>';
  913. return $rv;
  914. }
  915. /**
  916. * FilePicker JS template for popup dialogue window asking for action when file with the same name already exists (multiple-file version).
  917. *
  918. * Must have one top element, CSS for this element must define width and height of the window;
  919. *
  920. * content of element with class 'fp-dlg-text' will be replaced with dialog text;
  921. * elements with classes 'fp-dlg-butoverwrite', 'fp-dlg-butrename' and 'fp-dlg-butcancel' will
  922. * hold onclick events;
  923. *
  924. * content of element with class 'fp-dlg-butrename' will be substituted with appropriate string
  925. * (Note that it may have long text)
  926. *
  927. * @return string
  928. */
  929. private function fp_js_template_processexistingfilemultiple() {
  930. $rv = '
  931. <div class="file-picker fp-dlg">
  932. <p class="fp-dlg-text"></p>
  933. <a class="fp-dlg-butoverwrite fp-panel-button" href="#">'.get_string('overwrite', 'repository').'</a>
  934. <a class="fp-dlg-butcancel fp-panel-button" href="#">'.get_string('cancel').'</a>
  935. <a class="fp-dlg-butrename fp-panel-button" href="#"></a>
  936. <br/>
  937. <a class="fp-dlg-butoverwriteall fp-panel-button" href="#">'.get_string('overwriteall', 'repository').'</a>
  938. <a class="fp-dlg-butrenameall fp-panel-button" href="#">'.get_string('renameall', 'repository').'</a>
  939. </div>';
  940. return $rv;
  941. }
  942. /**
  943. * FilePicker JS template for repository login form including templates for each element type
  944. *
  945. * Must contain one <form> element with templates for different input types inside:
  946. * Elements with classes 'fp-login-popup', 'fp-login-textarea', 'fp-login-select' and
  947. * 'fp-login-input' are templates for displaying respective login form elements. Inside
  948. * there must be exactly one element with type <button>, <textarea>, <select> or <input>
  949. * (i.e. fp-login-popup should have <button>, fp-login-textarea should have <textarea>, etc.);
  950. * They may also contain the <label> element and it's content will be substituted with
  951. * label;
  952. *
  953. * You can also define elements with classes 'fp-login-checkbox', 'fp-login-text'
  954. * but if they are not found, 'fp-login-input' will be used;
  955. *
  956. * Element with class 'fp-login-radiogroup' will be used for group of radio inputs. Inside
  957. * it should hava a template for one radio input (with class 'fp-login-radio');
  958. *
  959. * Element with class 'fp-login-submit' will hold on click mouse event (form submission). It
  960. * will be removed if at least one popup element is present;
  961. *
  962. * @return string
  963. */
  964. private function fp_js_template_loginform() {
  965. $rv = '
  966. <div class="fp-login-form">
  967. <div class="fp-content-center">
  968. <form class="form-horizontal">
  969. <div class="fp-formset">
  970. <div class="fp-login-popup control-group clearfix">
  971. <div class="controls fp-popup">
  972. <button class="fp-login-popup-but btn-primary btn">'.get_string('login', 'repository').'</button>
  973. </div>
  974. </div>
  975. <div class="fp-login-textarea control-group clearfix">
  976. <div class="controls"><textarea></textarea></div>
  977. </div>
  978. <div class="fp-login-select control-group clearfix">
  979. <label class="control-label"></label>
  980. <div class="controls"><select></select></div>
  981. </div>';
  982. // HACK to prevent browsers from automatically inserting the user's password into the wrong fields.
  983. $rv .= prevent_form_autofill_password();
  984. $rv .= '
  985. <div class="fp-login-input control-group clearfix">
  986. <label class="control-label"></label>
  987. <div class="controls"><input/></div>
  988. </div>
  989. <div class="fp-login-radiogroup control-group clearfix">
  990. <label class="control-label"></label>
  991. <div class="controls fp-login-radio"><input /> <label></label></div>
  992. </div>
  993. </div>
  994. <p><button class="fp-login-submit btn-primary btn">'.get_string('submit', 'repository').'</button></p>
  995. </form>
  996. </div>
  997. </div>';
  998. return $rv;
  999. }
  1000. /**
  1001. * Returns all FilePicker JavaScript templates as an array.
  1002. *
  1003. * @return array
  1004. */
  1005. public function filepicker_js_templates() {
  1006. $class_methods = get_class_methods($this);
  1007. $templates = array();
  1008. foreach ($class_methods as $method_name) {
  1009. if (preg_match('/^fp_js_template_(.*)$/', $method_name, $matches))
  1010. $templates[$matches[1]] = $this->$method_name();
  1011. }
  1012. return $templates;
  1013. }
  1014. /**
  1015. * Returns HTML for default repository searchform to be passed to Filepicker
  1016. *
  1017. * This will be used as contents for search form defined in generallayout template
  1018. * (form with id {TOOLSEARCHID}).
  1019. * Default contents is one text input field with name="s"
  1020. */
  1021. public function repository_default_searchform() {
  1022. $searchinput = html_writer::label(get_string('searchrepo', 'repository'),
  1023. 'reposearch', false, array('class' => 'accesshide'));
  1024. $searchinput .= html_writer::empty_tag('input', array('type' => 'text',
  1025. 'id' => 'reposearch', 'name' => 's', 'value' => get_string('search', 'repository')));
  1026. $str = html_writer::tag('div', $searchinput, array('class' => "fp-def-search"));
  1027. return $str;
  1028. }
  1029. }
  1030. /**
  1031. * Data structure representing a general moodle file tree viewer
  1032. *
  1033. * @copyright 2010 Dongsheng Cai
  1034. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  1035. * @since Moodle 2.0
  1036. */
  1037. class files_tree_viewer implements renderable {
  1038. public $tree;
  1039. public $path;
  1040. public $context;
  1041. /**
  1042. * Constructor of moodle_file_tree_viewer class
  1043. * @param file_info $file_info
  1044. * @param array $options
  1045. */
  1046. public function __construct(file_info $file_info, array $options = null) {
  1047. global $CFG;
  1048. //note: this MUST NOT use get_file_storage() !!!!!!!!!!!!!!!!!!!!!!!!!!!!
  1049. $this->options = (array)$options;
  1050. $this->context = $options['context'];
  1051. $this->tree = array();
  1052. $children = $file_info->get_children();
  1053. $current_file_params = $file_info->get_params();
  1054. $parent_info = $file_info->get_parent();
  1055. $level = $parent_info;
  1056. $this->path = array();
  1057. while ($level) {
  1058. $params = $level->get_params();
  1059. $context = context::instance_by_id($params['contextid']);
  1060. // $this->context is current context
  1061. if ($context->id != $this->context->id or empty($params['filearea'])) {
  1062. break;
  1063. }
  1064. // unset unused parameters
  1065. unset($params['component']);
  1066. unset($params['filearea']);
  1067. unset($params['filename']);
  1068. unset($params['itemid']);
  1069. $url = new moodle_url('/files/index.php', $params);
  1070. $this->path[] = html_writer::link($url, $level->get_visible_name());
  1071. $level = $level->get_parent();
  1072. }
  1073. $this->path = array_reverse($this->path);
  1074. if ($current_file_params['filepath'] != '/') {
  1075. $this->path[] = $file_info->get_visible_name();
  1076. }
  1077. foreach ($children as $child) {
  1078. $filedate = $child->get_timemodified();
  1079. $filesize = $child->get_filesize();
  1080. $mimetype = $child->get_mimetype();
  1081. $params = $child->get_params();
  1082. unset($params['component']);
  1083. unset($params['filearea']);
  1084. unset($params['filename']);
  1085. unset($params['itemid']);
  1086. $fileitem = array(
  1087. 'params' => $params,
  1088. 'filename' => $child->get_visible_name(),
  1089. 'mimetype' => $child->get_mimetype(),
  1090. 'filedate' => $filedate ? $filedate : '',
  1091. 'filesize' => $filesize ? $filesize : ''
  1092. );
  1093. $url = new moodle_url('/files/index.php', $params);
  1094. if ($child->is_directory()) {
  1095. $fileitem['isdir'] = true;
  1096. $fileitem['url'] = $url->out(false);
  1097. } else {
  1098. $fileitem['url'] = $child->get_url();
  1099. }
  1100. $this->tree[] = $fileitem;
  1101. }
  1102. }
  1103. }