$array_index++;
if ($item->nodeName == "item") {
+ $identifierref = '';
+ if ($item->hasAttribute('identifierref')) {
+ $identifierref = $item->getAttribute('identifierref');
+ }
- $identifierref = $xpath->query('@identifierref', $item);
- $identifierref = !empty($identifierref->item(0)->nodeValue) ? $identifierref->item(0)->nodeValue : '';
-
- $title = $xpath->query('imscc:title', $item);
- $title = !empty($title->item(0)->nodeValue) ? $title->item(0)->nodeValue : '';
+ $title = '';
+ $titles = $xpath->query('imscc:title', $item);
+ if ($titles->length > 0) {
+ $title = $titles->item(0)->nodeValue;
+ }
$cc_type = $this->get_item_cc_type($identifierref);
$moodle_type = $this->convert_to_moodle_type($cc_type);
+ //Fix the label issue - MDL-33523
+ if (empty($identifierref) && empty($title)) {
+ $moodle_type = TYPE_UNKNOWN;
+ }
}
elseif ($item->nodeName == "resource") {
if (!empty($labels) && ($labels->length > 0)) {
$tname = 'course_files';
$dpath = cc2moodle::$path_to_manifest_folder . DIRECTORY_SEPARATOR . $tname;
- $rfpath = 'folder.gif';
+ $rfpath = 'files.gif';
$fpath = $dpath . DIRECTORY_SEPARATOR . $rfpath;
if (!file_exists($dpath)) {
mkdir($dpath);
}
//copy the folder.gif file
- $folder_gif = "{$CFG->dirroot}/pix/f/folder.gif";
+ $folder_gif = "{$CFG->dirroot}/pix/i/files.gif";
copy($folder_gif, $fpath);
$all_files[] = $rfpath;
}
if (!empty($labels) && ($labels->length > 0)) {
$tname = 'course_files';
$dpath = cc2moodle::$path_to_manifest_folder . DIRECTORY_SEPARATOR . $tname;
- $rfpath = 'folder.gif';
- $fpath = $dpath . DIRECTORY_SEPARATOR . 'folder.gif';
+ $rfpath = 'files.gif';
+ $fpath = $dpath . DIRECTORY_SEPARATOR . 'files.gif';
if (!file_exists($dpath)) {
mkdir($dpath);
}
//copy the folder.gif file
- $folder_gif = "{$CFG->dirroot}/pix/f/folder.gif";
+ $folder_gif = "{$CFG->dirroot}/pix/i/files.gif";
copy($folder_gif, $fpath);
$all_files[] = $rfpath;
}
'[#date_now#]');
$title = isset($instance['title']) && !empty($instance['title']) ? $instance['title'] : 'Untitled';
- $content = "<img src=\"$@FILEPHP@$$@SLASH@$"."folder.gif\" alt=\"Folder\" title=\"{$title}\" /> {$title}";
+ $content = "<img src=\"$@FILEPHP@$$@SLASH@$"."files.gif\" alt=\"Folder\" title=\"{$title}\" /> {$title}";
$replace_values = array($instance['instance'],
self::safexml($title),
self::safexml($content),
require_once($CFG->dirroot .'/blog/lib.php');
require_once($CFG->dirroot .'/blog/locallib.php');
+ if (empty($this->config)) {
+ $this->config = new stdClass();
+ }
+
if (empty($this->config->recentbloginterval)) {
$this->config->recentbloginterval = 8400;
}
// require the libs and do the work
require_once($CFG->dirroot .'/blog/lib.php');
+ if (empty($this->config)) {
+ $this->config = new stdClass();
+ }
+
if (empty($this->config->timewithin)) {
$this->config->timewithin = BLOCK_BLOG_TAGS_DEFAULTTIMEWITHIN;
}
}
}
- // Adjust destination to reflect the actual section
- $moveup = false;
- if ($section > $destination) {
- $destination++;
- $moveup = true;
- }
-
// If we move the highlighted section itself, then just highlight the destination.
// Adjust the higlighted section location if we move something over it either direction.
if ($section == $course->marker) {
course_set_marker($course->id, $destination);
- } elseif ($moveup && $section > $course->marker && $course->marker >= $destination) {
+ } elseif ($section > $course->marker && $course->marker >= $destination) {
course_set_marker($course->id, $course->marker+1);
- } elseif (!$moveup && $section < $course->marker && $course->marker <= $destination) {
+ } elseif ($section < $course->marker && $course->marker <= $destination) {
course_set_marker($course->id, $course->marker-1);
}
$this->assertFalse($neworder);
}
- public function test_move_section() {
+ public function test_move_section_down() {
global $DB;
$this->resetAfterTest(true);
}
ksort($oldsections);
+ // Test move section down..
move_section_to($course, 2, 4);
$sections = array();
foreach ($DB->get_records('course_sections', array('course'=>$course->id)) as $section) {
$this->assertEquals($oldsections[6], $sections[6]);
}
+ public function test_move_section_up() {
+ global $DB;
+ $this->resetAfterTest(true);
+
+ $this->getDataGenerator()->create_course(array('numsections'=>5), array('createsections'=>true));
+ $course = $this->getDataGenerator()->create_course(array('numsections'=>10), array('createsections'=>true));
+ $oldsections = array();
+ foreach ($DB->get_records('course_sections', array('course'=>$course->id)) as $section) {
+ $oldsections[$section->section] = $section->id;
+ }
+ ksort($oldsections);
+
+ // Test move section up..
+ move_section_to($course, 6, 4);
+ $sections = array();
+ foreach ($DB->get_records('course_sections', array('course'=>$course->id)) as $section) {
+ $sections[$section->section] = $section->id;
+ }
+ ksort($sections);
+
+ $this->assertEquals($oldsections[0], $sections[0]);
+ $this->assertEquals($oldsections[1], $sections[1]);
+ $this->assertEquals($oldsections[2], $sections[2]);
+ $this->assertEquals($oldsections[3], $sections[3]);
+ $this->assertEquals($oldsections[4], $sections[5]);
+ $this->assertEquals($oldsections[5], $sections[6]);
+ $this->assertEquals($oldsections[6], $sections[4]);
+ }
+
+ public function test_move_section_marker() {
+ global $DB;
+ $this->resetAfterTest(true);
+
+ $this->getDataGenerator()->create_course(array('numsections'=>5), array('createsections'=>true));
+ $course = $this->getDataGenerator()->create_course(array('numsections'=>10), array('createsections'=>true));
+
+ // Set course marker to the section we are going to move..
+ course_set_marker($course->id, 2);
+ // Verify that the course marker is set correctly.
+ $course = $DB->get_record('course', array('id' => $course->id));
+ $this->assertEquals(2, $course->marker);
+
+ // Test move the marked section down..
+ move_section_to($course, 2, 4);
+
+ // Verify that the coruse marker has been moved along with the section..
+ $course = $DB->get_record('course', array('id' => $course->id));
+ $this->assertEquals(4, $course->marker);
+
+ // Test move the marked section up..
+ move_section_to($course, 4, 3);
+
+ // Verify that the course marker has been moved along with the section..
+ $course = $DB->get_record('course', array('id' => $course->id));
+ $this->assertEquals(3, $course->marker);
+
+ // Test moving a non-marked section above the marked section..
+ move_section_to($course, 4, 2);
+
+ // Verify that the course marker has been moved down to accomodate..
+ $course = $DB->get_record('course', array('id' => $course->id));
+ $this->assertEquals(4, $course->marker);
+
+ // Test moving a non-marked section below the marked section..
+ move_section_to($course, 3, 6);
+
+ // Verify that the course marker has been up to accomodate..
+ $course = $DB->get_record('course', array('id' => $course->id));
+ $this->assertEquals(3, $course->marker);
+ }
+
public function test_get_course_display_name_for_list() {
global $CFG;
$this->resetAfterTest(true);
* Must have one top element, CSS for this element must define width and height of the window;
*
* content of element with class 'fp-dlg-text' will be replaced with dialog text;
- * elements with classes 'fp-dlg-butoverwrite', 'fp-dlg-butrename' and 'fp-dlg-butcancel' will
+ * elements with classes 'fp-dlg-butoverwrite', 'fp-dlg-butrename',
+ * 'fp-dlg-butoverwriteall', 'fp-dlg-butrenameall' and 'fp-dlg-butcancel' will
* hold onclick events;
*
* content of element with class 'fp-dlg-butrename' will be substituted with appropriate string
return preg_replace('/\{\!\}/', '', $rv);
}
+ /**
+ * FilePicker JS template for popup dialogue window asking for action when file with the same name already exists (multiple-file version).
+ *
+ * Must have one top element, CSS for this element must define width and height of the window;
+ *
+ * content of element with class 'fp-dlg-text' will be replaced with dialog text;
+ * elements with classes 'fp-dlg-butoverwrite', 'fp-dlg-butrename' and 'fp-dlg-butcancel' will
+ * hold onclick events;
+ *
+ * content of element with class 'fp-dlg-butrename' will be substituted with appropriate string
+ * (Note that it may have long text)
+ *
+ * @return string
+ */
+ private function fp_js_template_processexistingfilemultiple() {
+ $rv = '
+<div class="file-picker fp-dlg">
+ <p class="{!}fp-dlg-text"></p>
+ <a class="{!}fp-dlg-butoverwrite fp-panel-button" href="#">'.get_string('overwrite', 'repository').'</a>
+ <a class="{!}fp-dlg-butcancel fp-panel-button" href="#">'.get_string('cancel').'</a>
+ <a class="{!}fp-dlg-butrename fp-panel-button" href="#"></a>
+ <br/>
+ <a class="{!}fp-dlg-butoverwriteall fp-panel-button" href="#">'.get_string('overwriteall', 'repository').'</a>
+ <a class="{!}fp-dlg-butrenameall fp-panel-button" href="#">'.get_string('renameall', 'repository').'</a>
+</div>';
+ return preg_replace('/\{\!\}/', '', $rv);
+ }
+
/**
* FilePicker JS template for repository login form including templates for each element type
*
$string['failedloginattemptsall'] = '{$a->attempts} failed logins for {$a->accounts} accounts';
$string['feedback'] = 'Feedback';
$string['file'] = 'File';
+$string['fileexists'] = 'There is already a file called {$a}';
$string['filemissing'] = '{$a} is missing';
$string['filetoolarge'] = 'is too large to upload';
$string['files'] = 'Files';
$string['uploadextension'] = 'File upload stopped by extension';
$string['uploadfailednotrecovering'] = 'Your file upload has failed because there was a problem with one of the files, {$a->name}.<br /> Here is a log of the problems:<br />{$a->problem}<br />Not recovering.';
$string['uploadfilelog'] = 'Upload log for file {$a}';
-$string['uploadformlimit'] = 'Uploaded file exceeded the maximum size limit set by the form';
+$string['uploadformlimit'] = 'Uploaded file {$a} exceeded the maximum size limit set by the form';
$string['uploadlabel'] = 'Title:';
$string['uploadnewfile'] = 'Upload new file';
$string['uploadnofilefound'] = 'No file was found - are you sure you selected one to upload?';
$string['operation'] = 'Operation';
$string['on'] = 'Enabled and visible';
$string['overwrite'] = 'Overwrite';
+$string['overwriteall'] = 'Overwrite all';
$string['personalrepositories'] = 'Available repository instances';
$string['plugin'] = 'Repository plug-ins';
$string['pluginerror'] = 'Errors in repository plugin.';
$string['refresh'] = 'Refresh';
$string['refreshnonjsfilepicker'] = 'Please close this window and refresh non-javascript file picker';
$string['removed'] = 'Repository removed';
+$string['renameall'] = 'Rename all';
$string['renameto'] = 'Rename to "{$a}"';
$string['repositories'] = 'Repositories';
$string['repository'] = 'Repository';
Y: null,
// URL for upload requests
url: M.cfg.wwwroot + '/repository/repository_ajax.php?action=upload',
+ // options may include: itemid, acceptedtypes, maxfiles, maxbytes, clientid, repositoryid, author
+ options: {},
// itemid used for repository upload
itemid: null,
// accepted filetypes accepted by this form passed to repository
acceptedtypes: [],
- // maximum number of files this form allows
- maxfiles: 0,
// maximum size of files allowed in this form
maxbytes: 0,
// unqiue id of this form field used for html elements
return; // no upload repository is enabled to upload to
}
+ this.options = options;
this.acceptedtypes = options.acceptedtypes;
this.clientid = options.clientid;
- this.maxfiles = options.maxfiles;
this.maxbytes = options.maxbytes;
this.itemid = options.itemid;
this.author = options.author;
* onto the page
*/
drag_enter_page: function(e) {
- if (!this.has_files(e) || this.reached_maxfiles()) {
+ if (!this.has_files(e)) {
return false;
}
* @param e event object
* @return boolean true if a valid file drag event
*/
- check_drag: function(e, maxfilesalert) {
+ check_drag: function(e) {
if (!this.has_files(e)) {
return false;
}
e.preventDefault();
e.stopPropagation();
- if (this.reached_maxfiles()) {
- if (typeof(maxfilesalert) != 'undefined' && maxfilesalert) {
- alert(M.util.get_string('maxfilesreached', 'moodle', this.maxfiles));
- }
- return false;
- }
-
return true;
},
var files = e._event.dataTransfer.files;
if (this.filemanager) {
- var currentfilecount = this.filemanager.filecount;
- if (((currentfilecount + files.length) > this.maxfiles) && (this.maxfiles != -1)) {
- alert(M.util.get_string('maxfilesreached', 'moodle', this.maxfiles));
- return false;
- }
- this.show_progress_spinner();
- for (var i=0, f; f=files[i]; i++) {
- if (this.upload_file(f)) {
- currentfilecount++;
- }
- }
+ var options = {
+ files: files,
+ options: this.options,
+ repositoryid: this.repositoryid,
+ currentfilecount: this.filemanager.filecount, // All files uploaded.
+ currentfiles: this.filemanager.options.list, // Only the current folder.
+ callback: Y.bind('update_filemanager', this)
+ };
+ var uploader = new dnduploader(options);
+ uploader.start_upload();
} else {
- this.show_progress_spinner();
if (files.length >= 1) {
- this.upload_file(files[0]);
+ options = {
+ files:[files[0]],
+ options: this.options,
+ repositoryid: this.repositoryid,
+ currentfilecount: 0,
+ currentfiles: [],
+ callback: Y.bind('callback', this)
+ };
+ uploader = new dnduploader(options);
+ uploader.start_upload();
}
}
return false;
},
- /**
- * Check if reached the maximumum number of allowed files
- *
- * @return boolean true if reached maximum number of files
- */
- reached_maxfiles: function() {
- if (this.filemanager) {
- if (this.filemanager.filecount >= this.maxfiles && this.maxfiles != -1) {
- return true;
- }
- }
- return false;
- },
-
/**
* Highlight the area where files could be dropped
*/
},
/**
- * Display a progress spinner in the destination node
+ * Tell the attached filemanager element (if any) to refresh on file
+ * upload
+ */
+ update_filemanager: function() {
+ if (this.filemanager) {
+ // update the filemanager that we've uploaded the files
+ this.filemanager.filepicker_callback();
+ }
+ }
+ };
+
+ var dnduploader = function(options) {
+ dnduploader.superclass.constructor.apply(this, arguments);
+ };
+
+ Y.extend(dnduploader, Y.Base, {
+ // The URL to send the upload data to.
+ api: M.cfg.wwwroot+'/repository/repository_ajax.php',
+ // Options passed into the filemanager/filepicker element.
+ options: {},
+ // The function to call when all uploads complete.
+ callback: null,
+ // The list of files dropped onto the element.
+ files: null,
+ // The ID of the 'upload' repository.
+ repositoryid: 0,
+ // Array of files already in the current folder (to check for name clashes).
+ currentfiles: null,
+ // Total number of files already uploaded (to check for exceeding limits).
+ currentfilecount: 0,
+ // The list of files to upload.
+ uploadqueue: [],
+ // This list of files with name clashes.
+ renamequeue: [],
+ // Set to true if the user has clicked on 'overwrite all'.
+ overwriteall: false,
+ // Set to true if the user has clicked on 'rename all'.
+ renameall: false,
+
+ /**
+ * Initialise the settings for the dnduploader
+ * @param object params - includes:
+ * options (copied from the filepicker / filemanager)
+ * repositoryid - ID of the upload repository
+ * callback - the function to call when uploads are complete
+ * currentfiles - the list of files already in the current folder in the filemanager
+ * currentfilecount - the total files already in the filemanager
+ * files - the list of files to upload
+ * @return void
+ */
+ initializer: function(params) {
+ this.options = params.options;
+ this.repositoryid = params.repositoryid;
+ this.callback = params.callback;
+ this.currentfiles = params.currentfiles;
+ this.currentfilecount = params.currentfilecount;
+
+ this.initialise_queue(params.files);
+ },
+
+ /**
+ * Entry point for starting the upload process (starts by processing any
+ * renames needed)
*/
- show_progress_spinner: function() {
- this.container.addClass('dndupload-uploading');
+ start_upload: function() {
+ this.process_renames(); // Automatically calls 'do_upload' once renames complete.
},
/**
- * Remove progress spinner in the destination node
+ * Display a message in a popup
+ * @param string msg - the message to display
+ * @param string type - 'error' or 'info'
*/
- hide_progress_spinner: function() {
- this.container.removeClass('dndupload-uploading');
+ print_msg: function(msg, type) {
+ var header = M.str.moodle.error;
+ if (type != 'error') {
+ type = 'info'; // one of only two types excepted
+ header = M.str.moodle.info;
+ }
+ if (!this.msg_dlg) {
+ this.msg_dlg_node = Y.Node.createWithFilesSkin(M.core_filepicker.templates.message);
+ this.msg_dlg_node.generateID();
+
+ this.msg_dlg = new Y.Panel({
+ srcNode : this.msg_dlg_node,
+ zIndex : 800000,
+ centered : true,
+ modal : true,
+ visible : false,
+ render : true
+ });
+ this.msg_dlg.plug(Y.Plugin.Drag,{handles:['#'+this.msg_dlg_node.get('id')+' .yui3-widget-hd']});
+ this.msg_dlg_node.one('.fp-msg-butok').on('click', function(e) {
+ e.preventDefault();
+ this.msg_dlg.hide();
+ }, this);
+ }
+
+ this.msg_dlg.set('headerContent', header);
+ this.msg_dlg_node.removeClass('fp-msg-info').removeClass('fp-msg-error').addClass('fp-msg-'+type)
+ this.msg_dlg_node.one('.fp-msg-text').setContent(msg);
+ this.msg_dlg.show();
},
/**
- * Tell the attached filemanager element (if any) to refresh on file
- * upload
+ * Check the size of each file and add to either the uploadqueue or, if there
+ * is a name clash, the renamequeue
+ * @param FileList files - the files to upload
+ * @return void
*/
- update_filemanager: function() {
- if (this.filemanager) {
- // update the filemanager that we've uploaded the files
- this.filemanager.filepicker_callback();
+ initialise_queue: function(files) {
+ this.uploadqueue = [];
+ this.renamequeue = [];
+
+ // Loop through the files and find any name clashes with existing files
+ var i;
+ for (i=0; i<files.length; i++) {
+ if (this.options.maxbytes > 0 && files[i].size > this.options.maxbytes) {
+ // Check filesize before attempting to upload
+ this.print_msg(M.util.get_string('uploadformlimit', 'moodle', files[i].name), 'error');
+ this.uploadqueue = []; // No uploads if one file is too big.
+ return;
+ }
+
+ if (this.has_name_clash(files[i].name)) {
+ this.renamequeue.push(files[i]);
+ } else {
+ if (!this.add_to_upload_queue(files[i], files[i].name, false)) {
+ return;
+ }
+ }
}
},
/**
- * Upload a single file via an AJAX call to the 'upload' repository
+ * Add a single file to the uploadqueue, whilst checking the maxfiles limit
+ * @param File file - the file to add
+ * @param string filename - the name to give the file on upload
+ * @param bool overwrite - true to overwrite the existing file
+ * @return bool true if added successfully
*/
- upload_file: function(file) {
- if (file.size > this.maxbytes && this.maxbytes > 0) {
- // Check filesize before attempting to upload
- this.hide_progress_spinner();
- alert(M.util.get_string('uploadformlimit', 'moodle')+"\n'"+file.name+"'");
+ add_to_upload_queue: function(file, filename, overwrite) {
+ if (!overwrite) {
+ this.currentfilecount++;
+ }
+ if (this.options.maxfiles > 0 && this.currentfilecount > this.options.maxfiles) {
+ // Too many files - abort entire upload.
+ this.uploadqueue = [];
+ this.renamequeue = [];
+ this.print_msg(M.util.get_string('maxfilesreached', 'moodle', this.options.maxfiles), 'error');
return false;
}
+ this.uploadqueue.push({file:file, filename:filename, overwrite:overwrite});
+ return true;
+ },
+
+ /**
+ * Take the next file from the renamequeue and ask the user what to do with
+ * it. Called recursively until the queue is empty, then calls do_upload.
+ * @return void
+ */
+ process_renames: function() {
+ if (this.renamequeue.length == 0) {
+ // All rename processing complete - start the actual upload.
+ this.do_upload();
+ return;
+ }
+ var multiplefiles = (this.renamequeue.length > 1);
+
+ // Get the next file from the rename queue.
+ var file = this.renamequeue.shift();
+ // Generate a non-conflicting name for it.
+ var newname = this.generate_unique_name(file.name);
+
+ // If the user has clicked on overwrite/rename ALL then process
+ // this file, as appropriate, then process the rest of the queue.
+ if (this.overwriteall) {
+ this.add_to_upload_queue(file, file.name, true);
+ this.process_renames();
+ return;
+ }
+ if (this.renameall) {
+ this.add_to_upload_queue(file, newname, false);
+ this.process_renames();
+ return;
+ }
+
+ // Ask the user what to do with this file.
+ var self = this;
+
+ var process_dlg_node;
+ if (multiplefiles) {
+ process_dlg_node = Y.Node.createWithFilesSkin(M.core_filepicker.templates.processexistingfilemultiple);
+ } else {
+ process_dlg_node = Y.Node.createWithFilesSkin(M.core_filepicker.templates.processexistingfile);
+ }
+ var node = process_dlg_node;
+ node.generateID();
+ var process_dlg = new Y.Panel({
+ srcNode : node,
+ headerContent: M.str.repository.fileexistsdialogheader,
+ zIndex : 800000,
+ centered : true,
+ modal : true,
+ visible : false,
+ render : true,
+ buttons : {}
+ });
+ process_dlg.plug(Y.Plugin.Drag,{handles:['#'+node.get('id')+' .yui3-widget-hd']});
+
+ // Overwrite original.
+ node.one('.fp-dlg-butoverwrite').on('click', function(e) {
+ e.preventDefault();
+ process_dlg.hide();
+ self.add_to_upload_queue(file, file.name, true);
+ self.process_renames();
+ }, this);
+
+ // Rename uploaded file.
+ node.one('.fp-dlg-butrename').on('click', function(e) {
+ e.preventDefault();
+ process_dlg.hide();
+ self.add_to_upload_queue(file, newname, false);
+ self.process_renames();
+ }, this);
+
+ // Cancel all uploads.
+ node.one('.fp-dlg-butcancel').on('click', function(e) {
+ e.preventDefault();
+ process_dlg.hide();
+ }, this);
+
+ // When we are at the file limit, only allow 'overwrite', not rename.
+ if (this.currentfilecount == this.options.maxfiles) {
+ node.one('.fp-dlg-butrename').setStyle('display', 'none');
+ if (multiplefiles) {
+ node.one('.fp-dlg-butrenameall').setStyle('display', 'none');
+ }
+ }
+
+ // If there are more files still to go, offer the 'overwrite/rename all' options.
+ if (multiplefiles) {
+ // Overwrite all original files.
+ node.one('.fp-dlg-butoverwriteall').on('click', function(e) {
+ e.preventDefault();
+ process_dlg.hide();
+ this.overwriteall = true;
+ self.add_to_upload_queue(file, file.name, true);
+ self.process_renames();
+ }, this);
+
+ // Rename all new files.
+ node.one('.fp-dlg-butrenameall').on('click', function(e) {
+ e.preventDefault();
+ process_dlg.hide();
+ this.renameall = true;
+ self.add_to_upload_queue(file, newname, false);
+ self.process_renames();
+ }, this);
+ }
+ node.one('.fp-dlg-text').setContent(M.util.get_string('fileexists', 'moodle', file.name));
+ process_dlg_node.one('.fp-dlg-butrename').setContent(M.util.get_string('renameto', 'repository', newname));
+
+ // Destroy the dialog once it has been hidden.
+ process_dlg.after('visibleChange', function(e) {
+ if (!process_dlg.get('visible')) {
+ process_dlg.destroy(true);
+ }
+ });
+
+ process_dlg.show();
+ },
+
+ /**
+ * Checks if there is already a file with the given name in the current folder
+ * or in the list of already uploading files
+ * @param string filename - the name to test
+ * @return bool true if the name already exists
+ */
+ has_name_clash: function(filename) {
+ // Check against the already uploaded files
+ var i;
+ for (i=0; i<this.currentfiles.length; i++) {
+ if (filename == this.currentfiles[i].filename) {
+ return true;
+ }
+ }
+ // Check against the uploading files that have already been processed
+ for (i=0; i<this.uploadqueue.length; i++) {
+ if (filename == this.uploadqueue[i].filename) {
+ return true;
+ }
+ }
+ return false;
+ },
+
+ /**
+ * Adds _NUMBER to the end of the filename and increments this number until
+ * a unique name is found
+ * @param string filename
+ * @return string the unique filename generated
+ */
+ generate_unique_name: function(filename) {
+ // Split the filename into the basename + extension.
+ var extension;
+ var basename;
+ var dotpos = filename.lastIndexOf('.');
+ if (dotpos == -1) {
+ basename = filename;
+ extension = '';
+ } else {
+ basename = filename.substr(0, dotpos);
+ extension = filename.substr(dotpos, filename.length);
+ }
+
+ // Look to see if the name already has _NN at the end of it.
+ var number = 0;
+ var hasnumber = basename.match(/^(.*)_(\d+)$/);
+ if (hasnumber != null) {
+ // Note the current number & remove it from the basename.
+ number = parseInt(hasnumber[2]);
+ basename = hasnumber[1];
+ }
+
+ // Loop through increating numbers until a unique name is found.
+ var newname;
+ do {
+ number++;
+ newname = basename + '_' + number + extension;
+ } while (this.has_name_clash(newname));
+
+ return newname;
+ },
+
+ /**
+ * Upload the next file from the uploadqueue - called recursively after each
+ * upload is complete, then handles the callback to the filemanager/filepicker
+ * @param lastresult - the last result from the server
+ */
+ do_upload: function(lastresult) {
+ if (this.uploadqueue.length > 0) {
+ var filedetails = this.uploadqueue.shift();
+ this.upload_file(filedetails.file, filedetails.filename, filedetails.overwrite);
+ } else {
+ this.uploadfinished(lastresult);
+ }
+ },
+
+ /**
+ * Run the callback to the filemanager/filepicker
+ */
+ uploadfinished: function(lastresult) {
+ this.callback(lastresult);
+ },
+
+ /**
+ * Log any errors generated
+ */
+ add_error: function(text, errorlevel) {
+ // TODO
+ console.log(text);
+ },
+
+ /**
+ * Upload a single file via an AJAX call to the 'upload' repository. Automatically
+ * calls do_upload as each upload completes.
+ * @param File file - the file to upload
+ * @param string filename - the name to give the file
+ * @param bool overwrite - true if the existing file should be overwritten
+ */
+ upload_file: function(file, filename, overwrite) {
// This would be an ideal place to use the Y.io function
// however, this does not support data encoded using the
var self = this;
xhr.onreadystatechange = function() { // Process the server response
if (xhr.readyState == 4) {
- self.hide_progress_spinner();
if (xhr.status == 200) {
var result = JSON.parse(xhr.responseText);
if (result) {
if (result.error) {
- alert(result.error);
- } else if (self.callback) {
+ self.add_error(result.error); // TODO add filename?
+ } else {
// Only update the filepicker if there were no errors
if (result.event == 'fileexists') {
// Do not worry about this, as we only care about the last
result.file = result.newfile.filename;
result.url = result.newfile.url;
}
- result.client_id = self.clientid;
- self.callback(result);
- } else {
- self.update_filemanager();
+ result.client_id = self.options.clientid;
}
}
+ self.processedfiles++;
+ self.do_upload(result); // continue uploading
} else {
- alert(M.util.get_string('serverconnection', 'error'));
+ self.add_error(M.util.get_string('serverconnection', 'error'));
+ this.uploadfinished();
}
}
};
// Prepare the data to send
var formdata = new FormData();
+ formdata.append('action', 'upload');
formdata.append('repo_upload_file', file); // The FormData class allows us to attach a file
formdata.append('sesskey', M.cfg.sesskey);
formdata.append('repo_id', this.repositoryid);
- formdata.append('itemid', this.itemid);
- if (this.author) {
- formdata.append('author', this.author);
+ formdata.append('itemid', this.options.itemid);
+ if (this.options.author) {
+ formdata.append('author', this.options.author);
+ }
+ if (this.options.filemanager) { // Filepickers do not have folders
+ formdata.append('savepath', this.options.filemanager.currentpath);
}
- if (this.filemanager) { // Filepickers do not have folders
- formdata.append('savepath', this.filemanager.currentpath);
+ formdata.append('title', filename);
+ if (overwrite) {
+ formdata.append('overwrite', 1);
}
- if (this.acceptedtypes.constructor == Array) {
- for (var i=0; i<this.acceptedtypes.length; i++) {
- formdata.append('accepted_types[]', this.acceptedtypes[i]);
+ // Accepted types can be either a string or an array, but an array is
+ // expected in the processing script, so make sure we are sending an array
+ if (this.options.acceptedtypes.constructor == Array) {
+ for (var i=0; i<this.options.acceptedtypes.length; i++) {
+ formdata.append('accepted_types[]', this.options.acceptedtypes[i]);
}
} else {
- formdata.append('accepted_types[]', this.acceptedtypes);
+ formdata.append('accepted_types[]', this.options.acceptedtypes);
}
// Send the file & required details
- xhr.open("POST", this.url, true);
+ xhr.open("POST", this.api, true);
xhr.send(formdata);
return true;
}
- };
+ });
dnduploadhelper.init(Y, options);
};
var button_addfile = this.filemanager.one('.fp-btn-add');
// setup 'add file' button
- // if maxfiles == -1, the no limit
- button_addfile.on('click', function(e) {
- e.preventDefault();
- var options = this.filepicker_options;
- options.formcallback = this.filepicker_callback;
- // XXX: magic here, to let filepicker use filemanager scope
- options.magicscope = this;
- options.savepath = this.currentpath;
- M.core_filepicker.show(Y, options);
- }, this);
+ button_addfile.on('click', this.show_filepicker, this);
+
+ var dndarrow = this.filemanager.one('.dndupload-arrow');
+ if (dndarrow) {
+ dndarrow.on('click', this.show_filepicker, this);
+ }
// setup 'make a folder' button
if (this.options.subdirs) {
}
}, this);
},
+
+ show_filepicker: function (e) {
+ // if maxfiles == -1, the no limit
+ e.preventDefault();
+ var options = this.filepicker_options;
+ options.formcallback = this.filepicker_callback;
+ // XXX: magic here, to let filepicker use filemanager scope
+ options.magicscope = this;
+ options.savepath = this.currentpath;
+ M.core_filepicker.show(Y, options);
+ },
+
print_path: function() {
var p = this.options.path;
this.pathbar.setContent('').addClass('empty');
case 'core_dndupload':
$module = array('name' => 'core_dndupload',
'fullpath' => '/lib/form/dndupload.js',
- 'requires' => array('node', 'event', 'json'),
- 'strings' => array(array('uploadformlimit', 'moodle'), array('droptoupload', 'moodle'), array('maxfilesreached', 'moodle'), array('dndenabled_inbox', 'moodle')));
+ 'requires' => array('node', 'event', 'json', 'core_filepicker'),
+ 'strings' => array(array('uploadformlimit', 'moodle'), array('droptoupload', 'moodle'), array('maxfilesreached', 'moodle'), array('dndenabled_inbox', 'moodle'), array('fileexists', 'moodle')));
break;
}
// let the plugin add the fields they want (either statically or not)
if (portfolio_static_function($this->plugin, 'has_admin_config')) {
- if (!$this->instance) {
- require_once($CFG->libdir . '/portfolio/plugin.php');
- require_once($CFG->dirroot . '/portfolio/' . $this->plugin . '/lib.php');
- call_user_func(array('portfolio_plugin_' . $this->plugin, 'admin_config_form'), $mform);
- } else {
- $this->instance->admin_config_form($mform);
- }
+ require_once($CFG->libdir . '/portfolio/plugin.php');
+ require_once($CFG->dirroot . '/portfolio/' . $this->plugin . '/lib.php');
+ call_user_func(array('portfolio_plugin_' . $this->plugin, 'admin_config_form'), $mform);
}
// and set the data if we have some.
}
$pluginerrors = array();
- if ($this->instance) {
- $pluginerrors = $this->instance->admin_config_validation($data);
- }
- else {
- $pluginerrors = portfolio_static_function($this->plugin, 'admin_config_validation', $data);
- }
+ $pluginerrors = portfolio_static_function($this->plugin, 'admin_config_validation', $data);
if (is_array($pluginerrors)) {
$errors = array_merge($errors, $pluginerrors);
}
*
* @param moodleform $mform passed by reference, add elements to it.
*/
- public function admin_config_form(&$mform) {}
+ public static function admin_config_form(&$mform) {}
/**
* Just like the moodle form validation function,
*
* @param array $data data from form.
*/
- public function admin_config_validation($data) {}
+ public static function admin_config_validation($data) {}
/**
* mform to display to the user exporting data using this plugin.
* Petr Skoda (skodak) - most of the coding & design
* Mojmir Volf, Eloy Lafuente, Antonio Vicent and others
-
-
-Project page:
-
-* https://github.com/skodak/moodle-mod_book
-* http://moodle.org/plugins/view.php?plugin=mod_book
-
-
-Installation:
-
-* http://docs.moodle.org/20/en/Installing_contributed_modules_or_plugins
-
-
-Issue tracker:
-
-* https://github.com/skodak/moodle-mod_book/issues?milestone=&labels=
-
-
Intentionally omitted features:
* more chapter levels - it would encourage teachers to write too much complex and long books, better use standard standalone HTML editor and import it as Resource. DocBook format is another suitable solution.
* PDF export - there is no elegant way AFAIK to convert HTML to PDF, use virtual PDF printer or better use DocBook format for authoring
* detailed student tracking (postponed till officially supported)
* export as zipped set of HTML pages - instead use browser command Save page as... in print view
-
-
-Future:
-
-* No more development planned
<?php
-// This file is part of Book module for Moodle - http://moodle.org/
+// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
}
/**
- * This is executed when the parser reaches the <OPTIONS> opening element
+ * This is executed when the parser reaches the <CHAPTERS> opening element
*/
public function on_book_chapters_start() {
$this->xmlwriter->begin_tag('chapters');
}
/**
- * This is executed when the parser reaches the closing </OPTIONS> element
+ * This is executed when the parser reaches the closing </CHAPTERS> element
*/
public function on_book_chapters_end() {
$this->xmlwriter->end_tag('chapters');
* Define all the restore steps that will be used by the restore_book_activity_task
*
* @package mod_book
- * @subpackage book
* @copyright 2010 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
<?php
-// This file is part of Book module for Moodle - http://moodle.org/
+// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
<?php
-// This file is part of Book module for Moodle - http://moodle.org/
+// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
<?php
-// This file is part of Book module for Moodle - http://moodle.org/
+// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
-
/**
* Book module upgrade code
*
<?php
-// This file is part of Book module for Moodle - http://moodle.org/
+// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// Header and strings.
-$PAGE->set_title(format_string($book->name));
-$PAGE->add_body_class('mod_book');
-$PAGE->set_heading(format_string($course->fullname));
+$PAGE->set_title($book->name);
+$PAGE->set_heading($course->fullname);
// Form processing.
if ($confirm) { // the operation was confirmed.
<?php
-// This file is part of Book module for Moodle - http://moodle.org/
+// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
}
// Otherwise fill and print the form.
-$PAGE->set_title(format_string($book->name));
-$PAGE->add_body_class('mod_book');
-$PAGE->set_heading(format_string($course->fullname));
+$PAGE->set_title($book->name);
+$PAGE->set_heading($course->fullname);
echo $OUTPUT->header();
echo $OUTPUT->heading(get_string('editingchapter', 'mod_book'));
<?php
-// This file is part of Book module for Moodle - http://moodle.org/
+// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
$chapter = $this->_customdata['chapter'];
$options = $this->_customdata['options'];
+ // Disabled subchapter option when editing first node.
+ $disabledmsg = null;
+ if ($chapter->pagenum == 1) {
+ $disabledmsg = get_string('subchapternotice', 'book');
+ }
+
$mform = $this->_form;
$mform->addElement('header', 'general', get_string('edit'));
$mform->setType('title', PARAM_RAW);
$mform->addRule('title', null, 'required', null, 'client');
- $mform->addElement('advcheckbox', 'subchapter', get_string('subchapter', 'mod_book'));
+ $mform->addElement('advcheckbox', 'subchapter', get_string('subchapter', 'mod_book'), $disabledmsg);
$mform->addElement('editor', 'content_editor', get_string('content', 'mod_book'), null, $options);
$mform->setType('content_editor', PARAM_RAW);
// set the defaults
$this->set_data($chapter);
}
+
+ function definition_after_data(){
+ $mform = $this->_form;
+ $pagenum = $mform->getElement('pagenum');
+ if ($pagenum->getValue() == 1) {
+ $mform->hardFreeze('subchapter');
+ }
+ }
}
<?php
-// This file is part of Book module for Moodle - http://moodle.org/
+// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
$currentsection = $book->section;
}
} else {
- $printsection = '<span class="smallinfo">'.userdate($book->timemodified)."</span>";
+ $printsection = html_writer::tag('span', userdate($book->timemodified), array('class' => 'smallinfo'));
}
- $class = $book->visible ? '' : 'class="dimmed"'; // hidden modules are dimmed
+ $class = $book->visible ? null : array('class' => 'dimmed'); // hidden modules are dimmed
$table->data[] = array (
$printsection,
- "<a $class href=\"view.php?id=$cm->id\">".format_string($book->name)."</a>",
+ html_writer::link(new moodle_url('view.php', array('id' => $cm->id)), format_string($book->name), $class),
format_module_intro('book', $book, $cm->id));
}
<?php
-// This file is part of Book plugin for Moodle - http://moodle.org/
+// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
$string['numbering3'] = 'Indented';
$string['numberingoptions'] = 'Available options for chapter formatting';
$string['numberingoptions_desc'] = 'Options for displaying chapters and subchapters in the table of contents';
-$string['chapterscount'] = 'Chapters';
$string['addafter'] = 'Add new chapter';
$string['confchapterdelete'] = 'Do you really want to delete this chapter?';
$string['confchapterdeleteall'] = 'Do you really want to delete this chapter and all its subchapters?';
$string['errorchapter'] = 'Error reading chapter of book.';
$string['page-mod-book-x'] = 'Any book module page';
-
+$string['subchapternotice'] = '(Only available once the first chapter has been created)';
$string['subplugintype_booktool'] = 'Book tool';
$string['subplugintype_booktool_plural'] = 'Book tools';
<?php
-// This file is part of Book module for Moodle - http://moodle.org/
+// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
*/
function book_get_numbering_types() {
global $CFG; // required for the include
+
require_once(dirname(__FILE__).'/locallib.php');
return array (
* @return void
*/
function book_extend_settings_navigation(settings_navigation $settingsnav, navigation_node $booknode) {
- global $USER, $PAGE, $CFG, $DB, $OUTPUT;
-
- if ($PAGE->cm->modname !== 'book') {
- return;
- }
+ global $USER, $PAGE;
$plugins = get_plugin_list('booktool');
foreach ($plugins as $plugin => $dir) {
<?php
-// This file is part of Book module for Moodle - http://moodle.org/
+// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
$first = false;
}
if (!$ch->subchapter) {
- $ch->prev = $prev;
- $ch->next = null;
- if ($prev) {
- $chapters[$prev]->next = $ch->id;
- }
if ($ch->hidden) {
if ($book->numbering == BOOK_NUM_NUMBERS) {
$ch->number = 'x';
$ch->parent = null;
$ch->subchapters = array();
} else {
- $ch->prev = $prevsub;
- $ch->next = null;
- if ($prevsub) {
- $chapters[$prevsub]->next = $ch->id;
- }
$ch->parent = $parent;
$ch->subchapters = null;
$chapters[$parent]->subchapters[$ch->id] = $ch->id;
$ch->number = $j;
}
}
+
if ($oldch->subchapter != $ch->subchapter or $oldch->pagenum != $ch->pagenum or $oldch->hidden != $ch->hidden) {
// update only if something changed
$DB->update_record('book_chapters', $ch);
return $title;
}
-/**
- * General logging to table
- * @param string $str1
- * @param string $str2
- * @param int $level
- * @return void
- */
-function book_log($str1, $str2, $level = 0) {
- switch ($level) {
- case 1:
- echo '<tr><td><span class="dimmed_text">'.$str1.'</span></td><td><span class="dimmed_text">'.$str2.'</span></td></tr>';
- break;
- case 2:
- echo '<tr><td><span style="color: rgb(255, 0, 0);">'.$str1.'</span></td><td><span style="color: rgb(255, 0, 0);">'.$str2.'</span></td></tr>';
- break;
- default:
- echo '<tr><td>'.$str1.'</class></td><td>'.$str2.'</td></tr>';
- break;
- }
-}
-
/**
* Add the book TOC sticky block to the 1st region available
*
function book_get_toc($chapters, $chapter, $book, $cm, $edit) {
global $USER, $OUTPUT;
- $toc = ''; // Representation of toc (HTML)
+ $toc = '';
$nch = 0; // Chapter number
$ns = 0; // Subchapter number
$first = 1;
switch ($book->numbering) {
case BOOK_NUM_NONE:
- $toc .= '<div class="book_toc_none">';
+ $toc .= html_writer::start_tag('div', array('class' => 'book_toc_none'));
break;
case BOOK_NUM_NUMBERS:
- $toc .= '<div class="book_toc_numbered">';
+ $toc .= html_writer::start_tag('div', array('class' => 'book_toc_numbered'));
break;
case BOOK_NUM_BULLETS:
- $toc .= '<div class="book_toc_bullets">';
+ $toc .= html_writer::start_tag('div', array('class' => 'book_toc_bullets'));
break;
case BOOK_NUM_INDENTED:
- $toc .= '<div class="book_toc_indented">';
+ $toc .= html_writer::start_tag('div', array('class' => 'book_toc_indented'));
break;
}
if ($edit) { // Teacher's TOC
- $toc .= '<ul>';
+ $toc .= html_writer::start_tag('ul');
$i = 0;
foreach ($chapters as $ch) {
$i++;
$title = trim(format_string($ch->title, true, array('context'=>$context)));
if (!$ch->subchapter) {
- $toc .= ($first) ? '<li>' : '</ul></li><li>';
+
+ if ($first) {
+ $toc .= html_writer::start_tag('li');
+ } else {
+ $toc .= html_writer::end_tag('ul');
+ $toc .= html_writer::end_tag('li');
+ $toc .= html_writer::start_tag('li');
+ }
+
if (!$ch->hidden) {
$nch++;
$ns = 0;
if ($book->numbering == BOOK_NUM_NUMBERS) {
$title = "x $title";
}
- $title = '<span class="dimmed_text">'.$title.'</span>';
+ $title = html_writer::tag('span', $title, array('class' => 'dimmed_text'));
}
} else {
- $toc .= ($first) ? '<li><ul><li>' : '<li>';
+
+ if ($first) {
+ $toc .= html_writer::start_tag('li');
+ $toc .= html_writer::start_tag('ul');
+ $toc .= html_writer::start_tag('li');
+ } else {
+ $toc .= html_writer::start_tag('li');
+ }
+
if (!$ch->hidden) {
$ns++;
if ($book->numbering == BOOK_NUM_NUMBERS) {
$title = "x.x $title";
}
}
- $title = '<span class="dimmed_text">'.$title.'</span>';
+ $title = html_writer::tag('span', $title, array('class' => 'dimmed_text'));
}
}
if ($ch->id == $chapter->id) {
- $toc .= '<strong>'.$title.'</strong>';
+ $toc .= html_writer::tag('strong', $title);
} else {
- $toc .= '<a title="'.s($title).'" href="view.php?id='.$cm->id.'&chapterid='.$ch->id.'">'.$title.'</a>';
+ $toc .= html_writer::link(new moodle_url('view.php', array('id' => $cm->id, 'chapterid' => $ch->id)), $title, array('title' => s($title)));
}
$toc .= ' ';
if ($i != 1) {
- $toc .= ' <a title="'.get_string('up').'" href="move.php?id='.$cm->id.'&chapterid='.$ch->id.
- '&up=1&sesskey='.$USER->sesskey.'"><img src="'.$OUTPUT->pix_url('t/up').'" class="iconsmall" alt="'.get_string('up').'" /></a>';
+ $toc .= html_writer::link(new moodle_url('move.php', array('id' => $cm->id, 'chapterid' => $ch->id, 'up' => '1', 'sesskey' => $USER->sesskey)),
+ $OUTPUT->pix_icon('t/up', get_string('up')), array('title' => get_string('up')));
}
if ($i != count($chapters)) {
- $toc .= ' <a title="'.get_string('down').'" href="move.php?id='.$cm->id.'&chapterid='.$ch->id.
- '&up=0&sesskey='.$USER->sesskey.'"><img src="'.$OUTPUT->pix_url('t/down').'" class="iconsmall" alt="'.get_string('down').'" /></a>';
+ $toc .= html_writer::link(new moodle_url('move.php', array('id' => $cm->id, 'chapterid' => $ch->id, 'up' => '0', 'sesskey' => $USER->sesskey)),
+ $OUTPUT->pix_icon('t/down', get_string('down')), array('title' => get_string('down')));
}
- $toc .= ' <a title="'.get_string('edit').'" href="edit.php?cmid='.$cm->id.'&id='.$ch->id.'"><img src="'.
- $OUTPUT->pix_url('t/edit').'" class="iconsmall" alt="'.get_string('edit').'" /></a>';
- $toc .= ' <a title="'.get_string('delete').'" href="delete.php?id='.$cm->id.'&chapterid='.$ch->id.
- '&sesskey='.$USER->sesskey.'"><img src="'.$OUTPUT->pix_url('t/delete').'" class="iconsmall" alt="'.get_string('delete').'" /></a>';
+ $toc .= html_writer::link(new moodle_url('edit.php', array('cmid' => $cm->id, 'id' => $ch->id)),
+ $OUTPUT->pix_icon('t/edit', get_string('edit')), array('title' => get_string('edit')));
+ $toc .= html_writer::link(new moodle_url('delete.php', array('id' => $cm->id, 'chapterid' => $ch->id, 'sesskey' => $USER->sesskey)),
+ $OUTPUT->pix_icon('t/delete', get_string('delete')), array('title' => get_string('delete')));
if ($ch->hidden) {
- $toc .= ' <a title="'.get_string('show').'" href="show.php?id='.$cm->id.'&chapterid='.$ch->id.
- '&sesskey='.$USER->sesskey.'"><img src="'.$OUTPUT->pix_url('t/show').'" class="iconsmall" alt="'.get_string('show').'" /></a>';
+ $toc .= html_writer::link(new moodle_url('show.php', array('id' => $cm->id, 'chapterid' => $ch->id, 'sesskey' => $USER->sesskey)),
+ $OUTPUT->pix_icon('t/show', get_string('show')), array('title' => get_string('show')));
} else {
- $toc .= ' <a title="'.get_string('hide').'" href="show.php?id='.$cm->id.'&chapterid='.$ch->id.
- '&sesskey='.$USER->sesskey.'"><img src="'.$OUTPUT->pix_url('t/hide').'" class="iconsmall" alt="'.get_string('hide').'" /></a>';
+ $toc .= html_writer::link(new moodle_url('show.php', array('id' => $cm->id, 'chapterid' => $ch->id, 'sesskey' => $USER->sesskey)),
+ $OUTPUT->pix_icon('t/hide', get_string('hide')), array('title' => get_string('hide')));
}
- $toc .= ' <a title="'.get_string('addafter', 'mod_book').'" href="edit.php?cmid='.$cm->id.
- '&pagenum='.$ch->pagenum.'&subchapter='.$ch->subchapter.'"><img src="'.
- $OUTPUT->pix_url('add', 'mod_book').'" class="iconsmall" alt="'.get_string('addafter', 'mod_book').'" /></a>';
+ $toc .= html_writer::link(new moodle_url('edit.php', array('cmid' => $cm->id, 'pagenum' => $ch->pagenum, 'subchapter' => $ch->subchapter)),
+ $OUTPUT->pix_icon('add', get_string('addafter', 'mod_book'), 'mod_book'), array('title' => get_string('addafter', 'mod_book')));
- $toc .= (!$ch->subchapter) ? '<ul>' : '</li>';
+
+ if (!$ch->subchapter) {
+ $toc .= html_writer::start_tag('ul');
+ } else {
+ $toc .= html_writer::end_tag('li');
+ }
$first = 0;
}
- $toc .= '</ul></li></ul>';
+
+ $toc .= html_writer::end_tag('ul');
+ $toc .= html_writer::end_tag('li');
+ $toc .= html_writer::end_tag('ul');
+
} else { // Normal students view
- $toc .= '<ul>';
+ $toc .= html_writer::start_tag('ul');
foreach ($chapters as $ch) {
$title = trim(format_string($ch->title, true, array('context'=>$context)));
if (!$ch->hidden) {
if (!$ch->subchapter) {
$nch++;
$ns = 0;
- $toc .= ($first) ? '<li>' : '</ul></li><li>';
+
+ if ($first) {
+ $toc .= html_writer::start_tag('li');
+ } else {
+ $toc .= html_writer::end_tag('ul');
+ $toc .= html_writer::end_tag('li');
+ $toc .= html_writer::start_tag('li');
+ }
+
if ($book->numbering == BOOK_NUM_NUMBERS) {
$title = "$nch $title";
}
} else {
$ns++;
- $toc .= ($first) ? '<li><ul><li>' : '<li>';
+
+ if ($first) {
+ $toc .= html_writer::start_tag('li');
+ $toc .= html_writer::start_tag('ul');
+ $toc .= html_writer::start_tag('li');
+ } else {
+ $toc .= html_writer::start_tag('li');
+ }
+
if ($book->numbering == BOOK_NUM_NUMBERS) {
$title = "$nch.$ns $title";
}
}
if ($ch->id == $chapter->id) {
- $toc .= '<strong>'.$title.'</strong>';
+ $toc .= html_writer::tag('strong', $title);
} else {
- $toc .= '<a title="'.s($title).'" href="view.php?id='.$cm->id.'&chapterid='.$ch->id.'">'.$title.'</a>';
+ $toc .= html_writer::link(new moodle_url('view.php', array('id' => $cm->id, 'chapterid' => $ch->id)), $title, array('title' => s($title)));
}
- $toc .= (!$ch->subchapter) ? '<ul>' : '</li>';
+
+ if (!$ch->subchapter) {
+ $toc .= html_writer::start_tag('ul');
+ } else {
+ $toc .= html_writer::end_tag('li');
+ }
+
$first = 0;
}
}
- $toc .= '</ul></li></ul>';
+
+ $toc .= html_writer::end_tag('ul');
+ $toc .= html_writer::end_tag('li');
+ $toc .= html_writer::end_tag('ul');
+
}
- $toc .= '</div>';
+ $toc .= html_writer::end_tag('div');
$toc = str_replace('<ul></ul>', '', $toc); // Cleanup of invalid structures.
<?php
-// This file is part of Book module for Moodle - http://moodle.org/
+// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
<?php
-// This file is part of Book module for Moodle - http://moodle.org/
+// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
<?php
-// This file is part of Book module for Moodle - http://moodle.org/
+// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
<?php
-// This file is part of Book module for Moodle - http://moodle.org/
+// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
-.mod_book .book_chapter_title {
+.path-mod-book .book_chapter_title {
font-family: Tahoma, Verdana, Arial, Helvetica, sans-serif;
text-align: left;
font-size: large;
margin-bottom: 20px;
}
-.mod_book img.bigicon {
+.path-mod-book img.bigicon {
vertical-align: middle;
margin-right: 4px;
margin-left: 4px;
border: 0px;
}
-.mod_book .navtop {
+.path-mod-book .navtop {
text-align: right;
margin-bottom: 0.5em;
}
-.mod_book .navbottom {
+.path-mod-book .navbottom {
text-align: right;
}
/* == Fake toc block == */
/* toc style NONE */
-.mod_book .book_toc_none {
+.path-mod-book .book_toc_none {
font-size: 0.8em;
}
-.mod_book .book_toc_none ul {
+.path-mod-book .book_toc_none ul {
margin-left: 5px;
padding-left: 0px;
}
-.mod_book .book_toc_none ul ul {
+.path-mod-book .book_toc_none ul ul {
margin-left: 0px;
padding-left: 0px;
}
-.mod_book .book_toc_none li {
+.path-mod-book .book_toc_none li {
margin-top: 5px;
list-style: none;
}
-.mod_book .book_toc_none li li {
+.path-mod-book .book_toc_none li li {
margin-top: 0px;
list-style: none;
}
/* toc style NUMBERED */
-.mod_book .book_toc_numbered {
+.path-mod-book .book_toc_numbered {
font-size: 0.8em;
}
-.mod_book .book_toc_numbered ul {
+.path-mod-book .book_toc_numbered ul {
margin-left: 5px;
padding-left: 0px;
}
-.mod_book .book_toc_numbered ul ul {
+.path-mod-book .book_toc_numbered ul ul {
margin-left: 0px;
padding-left: 0px;
}
-.mod_book .book_toc_numbered li {
+.path-mod-book .book_toc_numbered li {
margin-top: 5px;
list-style: none;
}
-.mod_book .book_toc_numbered li li {
+.path-mod-book .book_toc_numbered li li {
margin-top: 0px;
list-style: none;
}
/*toc style BULLETS */
-.mod_book .book_toc_bullets {
+.path-mod-book .book_toc_bullets {
font-size: 0.8em;
}
-.mod_book .book_toc_bullets ul {
+.path-mod-book .book_toc_bullets ul {
margin-left: 5px;
padding-left: 0px;
}
-.mod_book .book_toc_bullets ul ul {
+.path-mod-book .book_toc_bullets ul ul {
margin-left: 20px;
padding-left: 0px;
}
-.mod_book .book_toc_bullets li {
+.path-mod-book .book_toc_bullets li {
margin-top: 5px;
list-style: none;
}
-.mod_book .book_toc_bullets li li {
+.path-mod-book .book_toc_bullets li li {
margin-top: 0px;
list-style: circle;
}
/* toc style INDENTED*/
-.mod_book .book_toc_indented {
+.path-mod-book .book_toc_indented {
font-size: 0.8em;
}
-.mod_book .book_toc_indented ul {
+.path-mod-book .book_toc_indented ul {
margin-left: 5px;
padding-left: 0px;
}
-.mod_book .book_toc_indented ul ul {
+.path-mod-book .book_toc_indented ul ul {
margin-left: 15px;
padding-left: 0px;
}
-.mod_book .book_toc_indented li {
+.path-mod-book .book_toc_indented li {
margin-top: 5px;
list-style: none;
}
-.mod_book .book_toc_indented li li {
+.path-mod-book .book_toc_indented li li {
margin-top: 0px;
list-style: none;
}
<?php
-// This file is part of Book module for Moodle - http://moodle.org/
+// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
<?php
-// This file is part of Book module for Moodle - http://moodle.org/
+// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
<?php
-// This file is part of Book plugin for Moodle - http://moodle.org/
+// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
require_capability('mod/book:read', $context);
require_capability('booktool/exportimscp:export', $context);
-$strbooks = get_string('modulenameplural', 'book');
-$strbook = get_string('modulename', 'book');
-$strtop = get_string('top', 'book');
-
add_to_log($course->id, 'book', 'exportimscp', 'tool/exportimscp/index.php?id='.$cm->id, $book->id, $cm->id);
$file = booktool_exportimscp_build_package($book, $context);
<?php
-// This file is part of Book plugin for Moodle - http://moodle.org/
+// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
<?php
-// This file is part of Book plugin for Moodle - http://moodle.org/
+// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
* @param navigation_node $node The node to add module settings to
*/
function booktool_exportimscp_extend_settings_navigation(settings_navigation $settings, navigation_node $node) {
- global $USER, $PAGE, $CFG, $DB, $OUTPUT;
-
- if ($PAGE->cm->modname !== 'book') {
- return;
- }
+ global $PAGE;
if (has_capability('booktool/exportimscp:export', $PAGE->cm->context)) {
$url = new moodle_url('/mod/book/tool/exportimscp/index.php', array('id'=>$PAGE->cm->id));
<?php
-// This file is part of Book plugin for Moodle - http://moodle.org/
+// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
<?php
-// This file is part of Book plugin for Moodle - http://moodle.org/
+// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
<?php
-// This file is part of Book module for Moodle - http://moodle.org/
+// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
<?php
-// This file is part of Book module for Moodle - http://moodle.org/
+// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
<?php
-// This file is part of Book module for Moodle - http://moodle.org/
+// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
$chapter = false;
}
-$PAGE->set_title(format_string($book->name));
-$PAGE->add_body_class('mod_book');
-$PAGE->set_heading(format_string($course->fullname));
+$PAGE->set_title($book->name);
+$PAGE->set_heading($course->fullname);
// Prepare the page header.
$strbook = get_string('modulename', 'mod_book');
<?php
-// This file is part of Book plugin for Moodle - http://moodle.org/
+// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
<?php
-// This file is part of Book plugin for Moodle - http://moodle.org/
+// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
* @param navigation_node $node The node to add module settings to
*/
function booktool_importhtml_extend_settings_navigation(settings_navigation $settings, navigation_node $node) {
- global $USER, $PAGE, $CFG, $DB, $OUTPUT;
-
- if ($PAGE->cm->modname !== 'book') {
- return;
- }
+ global $PAGE;
if (has_capability('booktool/importhtml:import', $PAGE->cm->context)) {
$url = new moodle_url('/mod/book/tool/importhtml/index.php', array('id'=>$PAGE->cm->id));
<?php
-// This file is part of Book plugin for Moodle - http://moodle.org/
+// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
<?php
-// This file is part of Book plugin for Moodle - http://moodle.org/
+// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
<?php
-// This file is part of Book module for Moodle - http://moodle.org/
+// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
<?php
-// This file is part of Book module for Moodle - http://moodle.org/
+// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
<?php
-// This file is part of Book module for Moodle - http://moodle.org/
+// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
<?php
-// This file is part of Book plugin for Moodle - http://moodle.org/
+// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
<?php
-// This file is part of Book plugin for Moodle - http://moodle.org/
+// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
function booktool_print_extend_settings_navigation(settings_navigation $settings, navigation_node $node) {
global $USER, $PAGE, $CFG, $DB, $OUTPUT;
- if ($PAGE->cm->modname !== 'book') {
- return;
- }
-
$params = $PAGE->url->params();
-
if (empty($params['id']) or empty($params['chapterid'])) {
return;
}
<?php
-// This file is part of Book plugin for Moodle - http://moodle.org/
+// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
switch ($book->numbering) {
case BOOK_NUM_NONE:
- $toc .= '<div class="book_toc_none">';
+ $toc .= html_writer::start_tag('div', array('class' => 'book_toc_none'));
break;
case BOOK_NUM_NUMBERS:
- $toc .= '<div class="book_toc_numbered">';
+ $toc .= html_writer::start_tag('div', array('class' => 'book_toc_numbered'));
break;
case BOOK_NUM_BULLETS:
- $toc .= '<div class="book_toc_bullets">';
+ $toc .= html_writer::start_tag('div', array('class' => 'book_toc_bullets'));
break;
case BOOK_NUM_INDENTED:
- $toc .= '<div class="book_toc_indented">';
+ $toc .= html_writer::start_tag('div', array('class' => 'book_toc_indented'));
break;
}
- $toc .= '<a name="toc"></a>'; // Representation of toc (HTML).
+ $toc .= html_writer::tag('a', '', array('name' => 'toc')); // Representation of toc (HTML).
if ($book->customtitles) {
- $toc .= '<h1>'.get_string('toc', 'mod_book').'</h1>';
+ $toc .= html_writer::tag('h1', get_string('toc', 'mod_book'));
} else {
- $toc .= '<p class="book_chapter_title">'.get_string('toc', 'mod_book').'</p>';
+ $toc .= html_writer::tag('p', get_string('toc', 'mod_book'), array('class' => 'book_chapter_title'));
}
- $toc .= '<ul>';
+ $toc .= html_writer::start_tag('ul');
foreach ($chapters as $ch) {
if (!$ch->hidden) {
$title = book_get_chapter_title($ch->id, $chapters, $book, $context);
if (!$ch->subchapter) {
- $toc .= $first ? '<li>' : '</ul></li><li>';
+
+ if ($first) {
+ $toc .= html_writer::start_tag('li');
+ } else {
+ $toc .= html_writer::end_tag('ul');
+ $toc .= html_writer::end_tag('li');
+ $toc .= html_writer::start_tag('li');
+ }
+
} else {
- $toc .= $first ? '<li><ul><li>' : '<li>';
+
+ if ($first) {
+ $toc .= html_writer::start_tag('li');
+ $toc .= html_writer::start_tag('ul');
+ $toc .= html_writer::start_tag('li');
+ } else {
+ $toc .= html_writer::start_tag('li');
+ }
+
}
$titles[$ch->id] = $title;
- $toc .= '<a title="'.s($title).'" href="#ch'.$ch->id.'">'.$title.'</a>';
- $toc .= (!$ch->subchapter) ? '<ul>' : '</li>';
+ $toc .= html_writer::link(new moodle_url('#ch'.$ch->id), $title, array('title' => s($title)));
+ if (!$ch->subchapter) {
+ $toc .= html_writer::start_tag('ul');
+ } else {
+ $toc .= html_writer::end_tag('li');
+ }
$first = false;
}
}
- $toc .= '</ul></li></ul>';
- $toc .= '</div>';
+
+ $toc .= html_writer::end_tag('ul');
+ $toc .= html_writer::end_tag('li');
+ $toc .= html_writer::end_tag('ul');
+ $toc .= html_writer::end_tag('div');
+
$toc = str_replace('<ul></ul>', '', $toc); // Cleanup of invalid structures.
return array($toc, $titles);
<?php
-// This file is part of Book plugin for Moodle - http://moodle.org/
+// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
<?php
-// This file is part of Book module for Moodle - http://moodle.org/
+// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
<?php
-// This file is part of Book module for Moodle - http://moodle.org/
+// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
$strtoc = get_string('toc', 'mod_book');
// prepare header
-$PAGE->set_title(format_string($book->name));
-$PAGE->add_body_class('mod_book');
-$PAGE->set_heading(format_string($course->fullname));
+$PAGE->set_title($book->name);
+$PAGE->set_heading($course->fullname);
book_add_fake_block($chapters, $chapter, $book, $cm, $edit);
echo '<div class="info"><a href="'.$link.'">'.format_string($entry->concept, true).'</a></div>';
$entrycount += 1;
} else {
- $numnewentries = $DB->count_records_sql($countsql.$joins[0].$clausesql.$approvalsql.')', $params);
+ $numnewentries = $DB->count_records_sql($countsql.$joins[0].$clausesql.$approvalsql, $params);
echo '<div class="head"><div class="activityhead">'.get_string('andmorenewentries', 'glossary', $numnewentries - GLOSSARY_RECENT_ACTIVITY_LIMIT).'</div></div>';
break;
}
$data->timefinish = $this->apply_date_offset($data->timefinish);
$data->timemodified = $this->apply_date_offset($data->timemodified);
+ // Deals with up-grading pre-2.3 back-ups to 2.3+.
+ if (!isset($data->state)) {
+ if ($data->timefinish > 0) {
+ $data->state = 'finished';
+ } else {
+ $data->state = 'inprogress';
+ }
+ }
+
// The data is actually inserted into the database later in inform_new_usage_id.
$this->currentquizattempt = clone($data);
}
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true" NEXT="quizstatisticsid"/>
<FIELD NAME="quizstatisticsid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" PREVIOUS="id" NEXT="questionid"/>
<FIELD NAME="questionid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" PREVIOUS="quizstatisticsid" NEXT="subqid"/>
- <FIELD NAME="subqid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" PREVIOUS="questionid" NEXT="aid"/>
- <FIELD NAME="aid" TYPE="int" LENGTH="10" NOTNULL="false" SEQUENCE="false" PREVIOUS="subqid" NEXT="response"/>
+ <FIELD NAME="subqid" TYPE="char" LENGTH="100" NOTNULL="true" SEQUENCE="false" PREVIOUS="questionid" NEXT="aid"/>
+ <FIELD NAME="aid" TYPE="char" LENGTH="100" NOTNULL="false" SEQUENCE="false" PREVIOUS="subqid" NEXT="response"/>
<FIELD NAME="response" TYPE="text" LENGTH="big" NOTNULL="false" SEQUENCE="false" PREVIOUS="aid" NEXT="rcount"/>
<FIELD NAME="rcount" TYPE="int" LENGTH="10" NOTNULL="false" SEQUENCE="false" PREVIOUS="response" NEXT="credit"/>
<FIELD NAME="credit" TYPE="number" LENGTH="15" NOTNULL="true" SEQUENCE="false" DECIMALS="5" PREVIOUS="rcount"/>
// Moodle v2.2.0 release upgrade line.
// Put any upgrade step following this.
+ if ($oldversion < 2012061800) {
+
+ // Changing type of field subqid on table quiz_question_response_stats to char.
+ $table = new xmldb_table('quiz_question_response_stats');
+ $field = new xmldb_field('subqid', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null, 'questionid');
+
+ // Launch change of type for field subqid.
+ $dbman->change_field_type($table, $field);
+
+ // Statistics savepoint reached.
+ upgrade_plugin_savepoint(true, 2012061800, 'quiz', 'statistics');
+ }
+
+ if ($oldversion < 2012061801) {
+
+ // Changing type of field aid on table quiz_question_response_stats to char.
+ $table = new xmldb_table('quiz_question_response_stats');
+ $field = new xmldb_field('aid', XMLDB_TYPE_CHAR, '100', null, null, null, null, 'subqid');
+
+ // Launch change of type for field aid.
+ $dbman->change_field_type($table, $field);
+
+ // Statistics savepoint reached.
+ upgrade_plugin_savepoint(true, 2012061801, 'quiz', 'statistics');
+ }
+
return true;
}
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2012061700;
+$plugin->version = 2012061801;
$plugin->requires = 2012061700;
$plugin->cron = 18000;
$plugin->component = 'quiz_statistics';
}
}
- public function admin_config_form(&$mform) {
+ public static function admin_config_form(&$mform) {
global $CFG;
$mform->addElement('text', 'apikey', get_string('apikey', 'portfolio_boxnet'));
return true;
}
- public function admin_config_form(&$mform) {
+ public static function admin_config_form(&$mform) {
global $CFG;
$strrequired = get_string('required');
return;
}
$mainadmin = reset($admins);
+ $a = new stdClass;
+ $a->docsurl = get_docs_url('Google_OAuth_2.0_setup');
foreach ($admins as $admin) {
$message = new stdClass();
$message->userto = $admin;
$message->smallmessage = get_string('oauth2upgrade_message_small', 'portfolio_googledocs');
$message->subject = get_string('oauth2upgrade_message_subject', 'portfolio_googledocs');
- $message->fullmessage = get_string('oauth2upgrade_message_content', 'portfolio_googledocs');
- $message->fullmessagehtml = get_string('oauth2upgrade_message_content', 'portfolio_googledocs');
+ $message->fullmessage = get_string('oauth2upgrade_message_content', 'portfolio_googledocs', $a);
+ $message->fullmessagehtml = get_string('oauth2upgrade_message_content', 'portfolio_googledocs', $a);
$message->fullmessageformat = FORMAT_PLAIN;
$message->notification = 1;
message_send($message);
$string['nooauthcredentials'] = 'OAuth credentials required.';
$string['nooauthcredentials_help'] = 'To use the Google Docs portfolio plugin you must configure OAuth credentials in the portfolio settings.';
$string['nosessiontoken'] = 'A session token does not exist preventing export to google.';
-$string['oauthinfo'] = '<p>To use the google docs portfolio you must be registered with Google. Instructions for registing your installation with Google are described in <a href="{$a->docsurl}">Moodle Docs</a>. The redirect url should be set to:</p><p>{$a->callbackurl}</p>';
+$string['oauthinfo'] = '<p>To use this plugin, you must register your site with Google, as described in the documentation <a href="{$a->docsurl}">Google OAuth 2.0 setup</a>.</p><p>As part of the registration process, you will need to enter the following URL as \'Authorized Redirect URIs\':</p><p>{$a->callbackurl}</p>Once registered, you will be provided with a client ID and secret which can be used to configure all Google Docs and Picasa plugins.</p>';
$string['oauth2upgrade_message_subject'] = 'Important information regarding Google Docs portfolio plugin';
-$string['oauth2upgrade_message_content'] = 'As part of the upgrade to Moodle 2.3, the Google Docs portfolio plugin has been disabled due to changes in Googles API. To re-enable your plugin, you must configure oauth credentials in this plugin.';
-$string['oauth2upgrade_message_small'] = 'The Google Docs portfolio plugin has been disabled until configured with OAuth2';
+$string['oauth2upgrade_message_content'] = 'As part of the upgrade to Moodle 2.3, the Google Docs portfolio plugin has been disabled. To re-enable it, your Moodle site needs to be registered with Google, as described in the documentation {$a->docsurl}, in order to obtain a client ID and secret. The client ID and secret can then be used to configure all Google Docs and Picasa plugins.';
+$string['oauth2upgrade_message_small'] = 'This plugin has been disabled, as it requires configuration as described in the documentation Google OAuth 2.0 setup.';
$string['pluginname'] = 'Google Docs';
$string['sendfailed'] = 'The file {$a} failed to transfer to google';
$string['secret'] = 'Secret';
return array('clientid', 'secret');
}
- public function admin_config_form(&$mform) {
+ public static function admin_config_form(&$mform) {
$a = new stdClass;
- $a->docsurl = get_docs_url('Google_OAuth2_Setup');
+ $a->docsurl = get_docs_url('Google_OAuth_2.0_setup');
$a->callbackurl = google_oauth::callback_url()->out(false);
$mform->addElement('static', null, '', get_string('oauthinfo', 'portfolio_googledocs', $a));
return true;
}
- public function admin_config_form(&$mform) {
+ public static function admin_config_form(&$mform) {
$strrequired = get_string('required');
$hosts = self::get_mnet_hosts(); // this is called by sanity check but it's ok because it's cached
foreach ($hosts as $host) {
return;
}
$mainadmin = reset($admins);
+ $a = new stdClass;
+ $a->docsurl = get_docs_url('Google_OAuth_2.0_setup');
foreach ($admins as $admin) {
$message = new stdClass();
$message->userto = $admin;
$message->smallmessage = get_string('oauth2upgrade_message_small', 'portfolio_picasa');
$message->subject = get_string('oauth2upgrade_message_subject', 'portfolio_picasa');
- $message->fullmessage = get_string('oauth2upgrade_message_content', 'portfolio_picasa');
- $message->fullmessagehtml = get_string('oauth2upgrade_message_content', 'portfolio_picasa');
+ $message->fullmessage = get_string('oauth2upgrade_message_content', 'portfolio_picasa', $a);
+ $message->fullmessagehtml = get_string('oauth2upgrade_message_content', 'portfolio_picasa', $a);
$message->fullmessageformat = FORMAT_PLAIN;
$message->notification = 1;
message_send($message);
$string['noauthtoken'] = 'An authentication token has not been recieved from google. Please ensure you are allowing moodle to access your google account';
$string['nooauthcredentials'] = 'OAuth credentials required.';
$string['nooauthcredentials_help'] = 'To use the Picasa portfolio plugin you must configure OAuth credentials in the portfolio settings.';
-$string['oauthinfo'] = '<p>To use the Picasa portfolio you must be registered with Google. Instructions for registing your installation with Google are described in <a href="{$a->docsurl}">Moodle Docs</a>. The redirect url should be set to:</p><p>{$a->callbackurl}</p>';
+$string['oauthinfo'] = '<p>To use this plugin, you must register your site with Google, as described in the documentation <a href="{$a->docsurl}">Google OAuth 2.0 setup</a>.</p><p>As part of the registration process, you will need to enter the following URL as \'Authorized Redirect URIs\':</p><p>{$a->callbackurl}</p>Once registered, you will be provided with a client ID and secret which can be used to configure all Google Docs and Picasa plugins.</p>';
$string['oauth2upgrade_message_subject'] = 'Important information regarding Picasa portfolio plugin';
-$string['oauth2upgrade_message_content'] = 'As part of the upgrade to Moodle 2.3, the Picasa portfolio plugin has been disabled due to changes in Googles API. To re-enable your plugin, you must configure oauth credentials in this plugin.';
-$string['oauth2upgrade_message_small'] = 'The Picasa portfolio plugin has been disabled until configured with OAuth2';
+$string['oauth2upgrade_message_content'] = 'As part of the upgrade to Moodle 2.3, the Picasa portfolio plugin has been disabled. To re-enable it, your Moodle site needs to be registered with Google, as described in the documentation {$a->docsurl}, in order to obtain a client ID and secret. The client ID and secret can then be used to configure all Google Docs and Picasa plugins.';
+$string['oauth2upgrade_message_small'] = 'This plugin has been disabled, as it requires configuration as described in the documentation Google OAuth 2.0 setup.';
$string['pluginname'] = 'Picasa';
$string['sendfailed'] = 'The file {$a} failed to transfer to picasa';
$string['secret'] = 'Secret';
return array('clientid', 'secret');
}
- public function admin_config_form(&$mform) {
+ public static function admin_config_form(&$mform) {
$a = new stdClass;
- $a->docsurl = get_docs_url('Google_OAuth2_Setup');
+ $a->docsurl = get_docs_url('Google_OAuth_2.0_setup');
$a->callbackurl = google_oauth::callback_url()->out(false);
$mform->addElement('static', null, '', get_string('oauthinfo', 'portfolio_picasa', $a));
--- /dev/null
+This files describes API changes in /portfolio/ portfolio system,
+information provided here is intended especially for developers.
+
+=== 2.3 ===
+
+required changes:
+* The following methods must now be declared static for php5 compatibility:
+ - admin_config_form
+ - admin_config_validation
$string['equellaurl'] = 'EQUELLA URL';
$string['equellaaction'] = 'EQUELLA action';
$string['equellaoptions'] = 'EQUELLA options';
+$string['equella:view'] = 'View EQUELLA repository';
$string['sharedid'] = 'Shared secret ID';
$string['sharedsecrets'] = 'Shared secret';
}
$mainadmin = reset($admins);
+ $a = new stdClass;
+ $a->docsurl = get_docs_url('Google_OAuth_2.0_setup');
foreach ($admins as $admin) {
$message = new stdClass();
$message->component = 'moodle';
$message->userto = $admin;
$message->smallmessage = get_string('oauth2upgrade_message_small', 'repository_googledocs');
$message->subject = get_string('oauth2upgrade_message_subject', 'repository_googledocs');
- $message->fullmessage = get_string('oauth2upgrade_message_content', 'repository_googledocs');
- $message->fullmessagehtml = get_string('oauth2upgrade_message_content', 'repository_googledocs');
+ $message->fullmessage = get_string('oauth2upgrade_message_content', 'repository_googledocs', $a);
+ $message->fullmessagehtml = get_string('oauth2upgrade_message_content', 'repository_googledocs', $a);
$message->fullmessageformat = FORMAT_PLAIN;
$message->notification = 1;
message_send($message);
$string['clientid'] = 'Client ID';
$string['configplugin'] = 'Configure Google Docs plugin';
$string['googledocs:view'] = 'View google docs repository';
-$string['oauthinfo'] = '<p>To use the Google Docs repository you must be registered with Google. Instructions for registing your installation with Google are described in <a href="{$a->docsurl}">Moodle Docs</a>. The redirect url should be set to:</p><p>{$a->callbackurl}</p>';
+$string['oauthinfo'] = '<p>To use this plugin, you must register your site with Google, as described in the documentation <a href="{$a->docsurl}">Google OAuth 2.0 setup</a>.</p><p>As part of the registration process, you will need to enter the following URL as \'Authorized Redirect URIs\':</p><p>{$a->callbackurl}</p>Once registered, you will be provided with a client ID and secret which can be used to configure all Google Docs and Picasa plugins.</p>';
$string['oauth2upgrade_message_subject'] = 'Important information regarding Google Docs repository plugin';
-$string['oauth2upgrade_message_content'] = 'As part of the upgrade to Moodle 2.3, the Google Docs repository plugin has been disabled due to changes in Googles API. To re-enable your plugin, you must add and reconfigure configure oauth credentials of this plugin.';
-$string['oauth2upgrade_message_small'] = 'The Google Docs repository plugin has been disabled until configured with OAuth2';
+$string['oauth2upgrade_message_content'] = 'As part of the upgrade to Moodle 2.3, the Google Docs portfolio plugin has been disabled. To re-enable it, your Moodle site needs to be registered with Google, as described in the documentation {$a->docsurl}, in order to obtain a client ID and secret. The client ID and secret can then be used to configure all Google Docs and Picasa plugins.';
+$string['oauth2upgrade_message_small'] = 'This plugin has been disabled, as it requires configuration as described in the documentation Google OAuth 2.0 setup.';
$string['pluginname'] = 'Google Docs';
$string['secret'] = 'Secret';
public static function type_config_form($mform, $classname = 'repository') {
$a = new stdClass;
- $a->docsurl = get_docs_url('Google_OAuth2_Setup');
+ $a->docsurl = get_docs_url('Google_OAuth_2.0_setup');
$a->callbackurl = google_oauth::callback_url()->out(false);
$mform->addElement('static', null, '', get_string('oauthinfo', 'repository_googledocs', $a));
return;
}
$mainadmin = reset($admins);
+ $a = new stdClass;
+ $a->docsurl = get_docs_url('Google_OAuth_2.0_setup');
foreach ($admins as $admin) {
$message = new stdClass();
$message->userto = $admin;
$message->smallmessage = get_string('oauth2upgrade_message_small', 'repository_picasa');
$message->subject = get_string('oauth2upgrade_message_subject', 'repository_picasa');
- $message->fullmessage = get_string('oauth2upgrade_message_content', 'repository_picasa');
- $message->fullmessagehtml = get_string('oauth2upgrade_message_content', 'repository_picasa');
+ $message->fullmessage = get_string('oauth2upgrade_message_content', 'repository_picasa', $a);
+ $message->fullmessagehtml = get_string('oauth2upgrade_message_content', 'repository_picasa', $a);
$message->fullmessageformat = FORMAT_PLAIN;
$message->notification = 1;
message_send($message);
$string['clientid'] = 'Client ID';
$string['configplugin'] = 'Picasa repository configuration';
-$string['oauthinfo'] = '<p>To use the Picasa repository you must be registered with Google. Instructions for registing your installation with Google are described in <a href="{$a->docsurl}">Moodle Docs</a>. The redirect url should be set to:</p><p>{$a->callbackurl}</p>';
+$string['oauthinfo'] = '<p>To use this plugin, you must register your site with Google, as described in the documentation <a href="{$a->docsurl}">Google OAuth 2.0 setup</a>.</p><p>As part of the registration process, you will need to enter the following URL as \'Authorized Redirect URIs\':</p><p>{$a->callbackurl}</p>Once registered, you will be provided with a client ID and secret which can be used to configure all Google Docs and Picasa plugins.</p>';
$string['oauth2upgrade_message_subject'] = 'Important information regarding Picasa repository plugin';
-$string['oauth2upgrade_message_content'] = 'As part of the upgrade to Moodle 2.3, the Picasa repository plugin has been disabled due to changes in Googles API. To re-enable your plugin, you must add and reconfigure configure oauth credentials of this plugin.';
-$string['oauth2upgrade_message_small'] = 'The Picasa repository plugin has been disabled until configured with OAuth2';
+$string['oauth2upgrade_message_content'] = 'As part of the upgrade to Moodle 2.3, the Picasa portfolio plugin has been disabled. To re-enable it, your Moodle site needs to be registered with Google, as described in the documentation {$a->docsurl}, in order to obtain a client ID and secret. The client ID and secret can then be used to configure all Google Docs and Picasa plugins.';
+$string['oauth2upgrade_message_small'] = 'This plugin has been disabled, as it requires configuration as described in the documentation Google OAuth 2.0 setup.';
$string['picasa:view'] = 'View picasa repository';
$string['pluginname'] = 'Picasa web album';
$string['secret'] = 'Secret';
public static function type_config_form($mform, $classname = 'repository') {
$a = new stdClass;
- $a->docsurl = get_docs_url('Google_OAuth2_Setup');
+ $a->docsurl = get_docs_url('Google_OAuth_2.0_setup');
$a->callbackurl = google_oauth::callback_url()->out(false);
$mform->addElement('static', null, '', get_string('oauthinfo', 'repository_picasa', $a));
$itemid = optional_param('itemid', 0, PARAM_INT);
$license = optional_param('license', $CFG->sitedefaultlicense, PARAM_TEXT);
$author = optional_param('author', '', PARAM_TEXT);
+ $overwriteexisting = optional_param('overwrite', false, PARAM_BOOL);
- return $this->process_upload($saveas_filename, $maxbytes, $types, $savepath, $itemid, $license, $author);
+ return $this->process_upload($saveas_filename, $maxbytes, $types, $savepath, $itemid, $license, $author, $overwriteexisting);
}
/**
* @param int $itemid optional the ID for this item within the file area
* @param string $license optional the license to use for this file
* @param string $author optional the name of the author of this file
+ * @param bool $overwriteexisting optional user has asked to overwrite the existing file
* @return object containing details of the file uploaded
*/
- public function process_upload($saveas_filename, $maxbytes, $types = '*', $savepath = '/', $itemid = 0, $license = null, $author = '') {
+ public function process_upload($saveas_filename, $maxbytes, $types = '*', $savepath = '/', $itemid = 0, $license = null, $author = '', $overwriteexisting = false) {
global $USER, $CFG;
if ((is_array($types) and in_array('*', $types)) or $types == '*') {
$record->userid = $USER->id;
if (repository::draftfile_exists($record->itemid, $record->filepath, $record->filename)) {
- $existingfilename = $record->filename;
- $unused_filename = repository::get_unused_filename($record->itemid, $record->filepath, $record->filename);
- $record->filename = $unused_filename;
- $stored_file = $fs->create_file_from_pathname($record, $_FILES[$elname]['tmp_name']);
- $event = array();
- $event['event'] = 'fileexists';
- $event['newfile'] = new stdClass;
- $event['newfile']->filepath = $record->filepath;
- $event['newfile']->filename = $unused_filename;
- $event['newfile']->url = moodle_url::make_draftfile_url($record->itemid, $record->filepath, $unused_filename)->out(false);
-
- $event['existingfile'] = new stdClass;
- $event['existingfile']->filepath = $record->filepath;
- $event['existingfile']->filename = $existingfilename;
- $event['existingfile']->url = moodle_url::make_draftfile_url($record->itemid, $record->filepath, $existingfilename)->out(false);
- return $event;
- } else {
- $stored_file = $fs->create_file_from_pathname($record, $_FILES[$elname]['tmp_name']);
+ if ($overwriteexisting) {
+ repository::delete_tempfile_from_draft($record->itemid, $record->filepath, $record->filename);
+ } else {
+ $existingfilename = $record->filename;
+ $unused_filename = repository::get_unused_filename($record->itemid, $record->filepath, $record->filename);
+ $record->filename = $unused_filename;
+ $stored_file = $fs->create_file_from_pathname($record, $_FILES[$elname]['tmp_name']);
+ $event = array();
+ $event['event'] = 'fileexists';
+ $event['newfile'] = new stdClass;
+ $event['newfile']->filepath = $record->filepath;
+ $event['newfile']->filename = $unused_filename;
+ $event['newfile']->url = moodle_url::make_draftfile_url($record->itemid, $record->filepath, $unused_filename)->out(false);
- return array(
- 'url'=>moodle_url::make_draftfile_url($record->itemid, $record->filepath, $record->filename)->out(false),
- 'id'=>$record->itemid,
- 'file'=>$record->filename);
+ $event['existingfile'] = new stdClass;
+ $event['existingfile']->filepath = $record->filepath;
+ $event['existingfile']->filename = $existingfilename;
+ $event['existingfile']->url = moodle_url::make_draftfile_url($record->itemid, $record->filepath, $existingfilename)->out(false);
+ return $event;
+ }
}
+
+ $stored_file = $fs->create_file_from_pathname($record, $_FILES[$elname]['tmp_name']);
+
+ return array(
+ 'url'=>moodle_url::make_draftfile_url($record->itemid, $record->filepath, $record->filename)->out(false),
+ 'id'=>$record->itemid,
+ 'file'=>$record->filename);
}
+
/**
* Checks the contents of the given file is not completely NULL - this can happen if a
* user drags & drops a folder onto a filemanager / filepicker element
/*.file-picker .fp-treeview .fp-folder .fp-icon, .filemanager .fp-treeview .fp-folder .fp-icon {}*/
/* first or middle sibling, no children */
.file-picker .ygtvtn, .filemanager .ygtvtn {background: url('[[pix:moodle|y/tn]]') 0px 0px no-repeat;width:17px;height:22px;}
-.dir-rtl .file-picker .ygtvtn, .filemanager .ygtvtn {background: url('[[pix:moodle|y/tn_rtl]]') 0px 0px no-repeat;width:17px;height:22px;}
+.dir-rtl .file-picker .ygtvtn {background: url('[[pix:moodle|y/tn_rtl]]') 0px 0px no-repeat;width:17px;height:22px;}
/* first or middle sibling, collapsable */
.file-picker .ygtvtm, .filemanager .ygtvtm {background: url('[[pix:moodle|y/tm]]') 0px 10px no-repeat;width:13px;height:12px;cursor:pointer;}
/* first or middle sibling, collapsable, hover */
.file-picker .ygtvtmh, .filemanager .ygtvtmh {background: url('[[pix:moodle|y/tm]]') 0px 10px no-repeat;width:13px;height:12px;cursor:pointer;}
/* first or middle sibling, expandable */
.file-picker .ygtvtp, .filemanager .ygtvtp {background: url('[[pix:moodle|y/tp]]') 0px 10px no-repeat;width:13px;height:12px;cursor:pointer;}
-.dir-rtl .file-picker .ygtvtp, .filemanager .ygtvtp {background: url('[[pix:moodle|y/tp_rtl]]') 0px 10px no-repeat;width:13px;height:12px;cursor:pointer;}
+.dir-rtl .file-picker .ygtvtp {background: url('[[pix:moodle|y/tp_rtl]]') 0px 10px no-repeat;width:13px;height:12px;cursor:pointer;}
/* first or middle sibling, expandable, hover */
.file-picker .ygtvtph, .filemanager .ygtvtph {background: url('[[pix:moodle|y/tp]]') 0px 10px no-repeat;width:13px;height:22px;cursor:pointer;}
-.dir-rtl .file-picker .ygtvtph, .filemanager .ygtvtph {background: url('[[pix:moodle|y/tp_rtl]]') 0px 10px no-repeat;width:13px;height:22px;cursor:pointer;}
+.dir-rtl .file-picker .ygtvtph {background: url('[[pix:moodle|y/tp_rtl]]') 0px 10px no-repeat;width:13px;height:22px;cursor:pointer;}
/* last sibling, no children */
.file-picker .ygtvln, .filemanager .ygtvln {background: url('[[pix:moodle|y/ln]]') 0px 0px no-repeat;width:17px;height:22px;}
-.dir-rtl .file-picker .ygtvln, .filemanager .ygtvln {background: url('[[pix:moodle|y/ln_rtl]]') 0px 0px no-repeat;width:17px;height:22px;}
+.dir-rtl .file-picker .ygtvln {background: url('[[pix:moodle|y/ln_rtl]]') 0px 0px no-repeat;width:17px;height:22px;}
/* Last sibling, collapsable */
.file-picker .ygtvlm, .filemanager .ygtvlm {background: url('[[pix:moodle|y/lm]]') 0px 10px no-repeat;width:13px;height:12px;cursor:pointer;}
/* Last sibling, collapsable, hover */
.file-picker .ygtvlmh, .filemanager .ygtvlmh {background: url('[[pix:moodle|y/lm]]') 0px 10px no-repeat;width:13px;height:12px;cursor:pointer;}
/* Last sibling, expandable */
.file-picker .ygtvlp, .filemanager .ygtvlp {background: url('[[pix:moodle|y/lp]]') 0px 10px no-repeat;width:13px;height:12px;cursor:pointer;}
-.dir-rtl .file-picker .ygtvlp, .filemanager .ygtvlp {background: url('[[pix:moodle|y/lp_rtl]]') 0px 10px no-repeat;width:13px;height:12px;cursor:pointer;}
+.dir-rtl .file-picker .ygtvlp {background: url('[[pix:moodle|y/lp_rtl]]') 0px 10px no-repeat;width:13px;height:12px;cursor:pointer;}
/* Last sibling, expandable, hover */
.file-picker .ygtvlph, .filemanager .ygtvlph {background: url('[[pix:moodle|y/lp]]') 0px 10px no-repeat;width:13px;height:12px;cursor:pointer;}
-.dir-rtl .file-picker .ygtvlph, .filemanager .ygtvlph {background: url('[[pix:moodle|y/lp_rtl]]') 0px 10px no-repeat;width:13px;height:12px;cursor:pointer;}
+.dir-rtl .file-picker .ygtvlph {background: url('[[pix:moodle|y/lp_rtl]]') 0px 10px no-repeat;width:13px;height:12px;cursor:pointer;}
/* Loading icon */
.file-picker .ygtvloading, .filemanager .ygtvloading {background: transparent url('[[pix:moodle|y/loading]]') 0 0 no-repeat;width:16px;height:22px;}
/* the style for the empty cells that are used for rendering the depth* of the node */