Skip to content

Commit

Permalink
MDL-38708 Added course overview files (most often images) to courses
Browse files Browse the repository at this point in the history
  • Loading branch information
marinaglancy committed Apr 2, 2013
1 parent ddbf9b6 commit d1f8c1b
Show file tree
Hide file tree
Showing 19 changed files with 211 additions and 12 deletions.
4 changes: 4 additions & 0 deletions admin/settings/appearance.php
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,10 @@
new lang_string('courselistshortnames_desc', 'admin'), 0));
$temp->add(new admin_setting_configtext('coursesperpage', new lang_string('coursesperpage', 'admin'), new lang_string('configcoursesperpage', 'admin'), 20, PARAM_INT));
$temp->add(new admin_setting_configtext('courseswithsummarieslimit', new lang_string('courseswithsummarieslimit', 'admin'), new lang_string('configcourseswithsummarieslimit', 'admin'), 10, PARAM_INT));
$temp->add(new admin_setting_configtext('courseoverviewfileslimit', new lang_string('courseoverviewfileslimit'),
new lang_string('configcourseoverviewfileslimit', 'admin'), 1, PARAM_INT));
$temp->add(new admin_setting_configtext('courseoverviewfilesext', new lang_string('courseoverviewfilesext'),
new lang_string('configcourseoverviewfilesext', 'admin'), '.jpg,.gif,.png'));
$ADMIN->add('appearance', $temp);

$temp = new admin_settingpage('ajax', new lang_string('ajaxuse'));
Expand Down
1 change: 1 addition & 0 deletions backup/moodle2/backup_stepslib.php
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,7 @@ protected function define_structure() {
$course->annotate_ids('grouping', 'defaultgroupingid');

$course->annotate_files('course', 'summary', null);
$course->annotate_files('course', 'overviewfiles', null);
$course->annotate_files('course', 'legacy', null);

// Return root element ($course)
Expand Down
1 change: 1 addition & 0 deletions backup/moodle2/restore_stepslib.php
Original file line number Diff line number Diff line change
Expand Up @@ -1459,6 +1459,7 @@ protected function after_execute() {

// Add course related files, without itemid to match
$this->add_related_files('course', 'summary', null);
$this->add_related_files('course', 'overviewfiles', null);

// Deal with legacy allowed modules.
if ($this->legacyrestrictmodules) {
Expand Down
7 changes: 7 additions & 0 deletions course/edit.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,14 @@

// Prepare course and the editor
$editoroptions = array('maxfiles' => EDITOR_UNLIMITED_FILES, 'maxbytes'=>$CFG->maxbytes, 'trusttext'=>false, 'noclean'=>true);
$overviewfilesoptions = course_overviewfiles_options($course);
if (!empty($course)) {
//add context for editor
$editoroptions['context'] = $coursecontext;
$course = file_prepare_standard_editor($course, 'summary', $editoroptions, $coursecontext, 'course', 'summary', 0);
if ($overviewfilesoptions) {
file_prepare_standard_filemanager($course, 'overviewfiles', $overviewfilesoptions, $coursecontext, 'course', 'overviewfiles', 0);
}

// Inject current aliases
$aliases = $DB->get_records('role_names', array('contextid'=>$coursecontext->id));
Expand All @@ -81,6 +85,9 @@
//editor should respect category context if course context is not set.
$editoroptions['context'] = $catcontext;
$course = file_prepare_standard_editor($course, 'summary', $editoroptions, null, 'course', 'summary', null);
if ($overviewfilesoptions) {
file_prepare_standard_filemanager($course, 'overviewfiles', $overviewfilesoptions, null, 'course', 'overviewfiles', 0);
}
}

// first create the form
Expand Down
9 changes: 8 additions & 1 deletion course/edit_form.php
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,16 @@ function definition() {
$mform->addElement('editor','summary_editor', get_string('coursesummary'), null, $editoroptions);
$mform->addHelpButton('summary_editor', 'coursesummary');
$mform->setType('summary_editor', PARAM_RAW);
$summaryfields = 'summary_editor';

if ($overviewfilesoptions = course_overviewfiles_options($course)) {
$mform->addElement('filemanager', 'overviewfiles_filemanager', get_string('courseoverviewfiles'), null, $overviewfilesoptions);
$mform->addHelpButton('overviewfiles_filemanager', 'courseoverviewfiles');
$summaryfields .= ',overviewfiles_filemanager';
}

if (!empty($course->id) and !has_capability('moodle/course:changesummary', $coursecontext)) {
$mform->hardFreeze('summary_editor');
$mform->hardFreeze($summaryfields);
}

$courseformats = get_sorted_course_formats(true);
Expand Down
54 changes: 54 additions & 0 deletions course/lib.php
Original file line number Diff line number Diff line change
Expand Up @@ -2174,6 +2174,53 @@ function save_local_role_names($courseid, $data) {
}
}

/**
* Returns options to use in course overviewfiles filemanager
*
* @param null|stdClass|course_in_list|int $course either object that has 'id' property or just the course id;
* may be empty if course does not exist yet (course create form)
* @return array|null array of options such as maxfiles, maxbytes, accepted_types, etc.
* or null if overviewfiles are disabled
*/
function course_overviewfiles_options($course) {
global $CFG;
if (empty($CFG->courseoverviewfileslimit)) {
return null;
}
$accepted_types = preg_split('/\s*,\s*/', trim($CFG->courseoverviewfilesext), -1, PREG_SPLIT_NO_EMPTY);
if (in_array('*', $accepted_types) || empty($accepted_types)) {
$accepted_types = '*';
} else {
// Since config for $CFG->courseoverviewfilesext is a text box, human factor must be considered.
// Make sure extensions are prefixed with dot unless they are valid typegroups
foreach ($accepted_types as $i => $type) {
if (substr($type, 0, 1) !== '.') {
require_once($CFG->libdir. '/filelib.php');
if (!count(file_get_typegroup('extension', $type))) {
// It does not start with dot and is not a valid typegroup, this is most likely extension.
$accepted_types[$i] = '.'. $type;
$corrected = true;
}
}
}
if (!empty($corrected)) {
set_config('courseoverviewfilesext', join(',', $accepted_types));
}
}
$options = array(
'maxfiles' => $CFG->courseoverviewfileslimit,
'maxbytes' => $CFG->maxbytes,
'subdirs' => 0,
'accepted_types' => $accepted_types
);
if (!empty($course->id)) {
$options['context'] = context_course::instance($course->id);
} else if (is_int($course) && $course > 0) {
$options['context'] = context_course::instance($course);
}
return $options;
}

/**
* Create a course and either return a $course object
*
Expand Down Expand Up @@ -2231,6 +2278,10 @@ function create_course($data, $editoroptions = NULL) {
$DB->set_field('course', 'summary', $data->summary, array('id'=>$newcourseid));
$DB->set_field('course', 'summaryformat', $data->summary_format, array('id'=>$newcourseid));
}
if ($overviewfilesoptions = course_overviewfiles_options($newcourseid)) {
// Save the course overviewfiles
$data = file_postupdate_standard_filemanager($data, 'overviewfiles', $overviewfilesoptions, $context, 'course', 'overviewfiles', 0);
}

// update course format options
course_get_format($newcourseid)->update_course_format_options($data);
Expand Down Expand Up @@ -2285,6 +2336,9 @@ function update_course($data, $editoroptions = NULL) {
if ($editoroptions) {
$data = file_postupdate_standard_editor($data, 'summary', $editoroptions, $context, 'course', 'summary', 0);
}
if ($overviewfilesoptions = course_overviewfiles_options($data->id)) {
$data = file_postupdate_standard_filemanager($data, 'overviewfiles', $overviewfilesoptions, $context, 'course', 'overviewfiles', 0);
}

if (!isset($data->category) or empty($data->category)) {
// prevent nulls and 0 in category field
Expand Down
19 changes: 18 additions & 1 deletion course/renderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -1070,7 +1070,7 @@ protected function coursecat_coursebox(coursecat_helper $chelper, $course, $addi
// If we display course in collapsed form but the course has summary or course contacts, display the link to the info page.
$content .= html_writer::start_tag('div', array('class' => 'moreinfo'));
if ($chelper->get_show_courses() < self::COURSECAT_SHOW_COURSES_EXPANDED) {
if ($course->has_summary() || $course->has_course_contacts()) {
if ($course->has_summary() || $course->has_course_contacts() || $course->has_course_overviewfiles()) {
$url = new moodle_url('/course/info.php', array('id' => $course->id));
$image = html_writer::empty_tag('img', array('src' => $this->output->pix_url('i/info'),
'alt' => $this->strings->summary));
Expand Down Expand Up @@ -1126,6 +1126,23 @@ protected function coursecat_coursebox_content(coursecat_helper $chelper, $cours
$content .= html_writer::end_tag('div'); // .summary
}

// display course overview files
foreach ($course->get_course_overviewfiles() as $file) {
$isimage = $file->is_valid_image();
$url = file_encode_url("$CFG->wwwroot/pluginfile.php",
'/'. $file->get_contextid(). '/'. $file->get_component(). '/'.
$file->get_filearea(). $file->get_filepath(). $file->get_filename(), !$isimage);
if ($isimage) {
$content .= html_writer::tag('div',
html_writer::empty_tag('img', array('src' => $url)),
array('class' => 'courseimage'));
} else {
$content .= html_writer::tag('div',
html_writer::link($url, $file->get_filename()),
array('class' => 'coursefile'));
}
}

// display course contacts. See course_in_list::get_course_contacts()
if ($course->has_course_contacts()) {
$content .= html_writer::start_tag('ul', array('class' => 'teachers'));
Expand Down
2 changes: 2 additions & 0 deletions lang/en/admin.php
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@
$string['configcookiehttponly'] = 'Enables new PHP 5.2.0 feature - browsers are instructed to send cookie with real http requests only, cookies should not be accessible by scripting languages. This is not supported in all browsers and it may not be fully compatible with current code. It helps to prevent some types of XSS attacks.';
$string['configcookiesecure'] = 'If server is accepting only https connections it is recommended to enable sending of secure cookies. If enabled please make sure that web server is not accepting http:// or set up permanent redirection to https:// address. When <em>wwwroot</em> address does not start with https:// this setting is turned off automatically.';
$string['configcountry'] = 'If you set a country here, then this country will be selected by default on new user accounts. To force users to choose a country, just leave this unset.';
$string['configcourseoverviewfilesext'] = 'Comma-separated list of allowed course overview files extensions';
$string['configcourseoverviewfileslimit'] = 'Limit the number of files course managers are allowed to add to the course. They will be accessible by anyone from outside of the course just like course name and/or summary';
$string['configcourserequestnotify'] = 'Type username of user to be notified when new course requested.';
$string['configcourserequestnotify2'] = 'Users who will be notified when a course is requested. Only users who can approve course requests are listed here.';
$string['configcoursesperpage'] = 'Enter the number of courses to be displayed per page in a course listing.';
Expand Down
4 changes: 4 additions & 0 deletions lang/en/moodle.php
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,10 @@
$string['coursehelpnumberweeks'] = 'Number of sections in the course (applies to certain course formats only).';
$string['coursehelpshowgrades'] = 'Enable the display of the gradebook. It does not prevent grades from being displayed within the individual activities.';
$string['coursehidden'] = 'This course is currently unavailable to students';
$string['courseoverviewfiles'] = 'Course overview files';
$string['courseoverviewfilesext'] = 'Course overview files extensions';
$string['courseoverviewfileslimit'] = 'Course overview files limit';
$string['courseoverviewfiles_help'] = 'Course overview files (usually images) are displayed in the list of courses together with summary';
$string['courseinfo'] = 'Course info';
$string['coursemessage'] = 'Message course users';
$string['coursenotaccessible'] = 'This course does not allow public access';
Expand Down
1 change: 1 addition & 0 deletions lang/en/repository.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
$string['activitybackup'] = 'Activity backup';
$string['areacategoryintro'] = 'Category introduction';
$string['areacourseintro'] = 'Course introduction';
$string['areacourseoverviewfiles'] = 'Course overview files';
$string['arearoot'] = 'System';
$string['areauserdraft'] = 'Drafts';
$string['areauserbackup'] = 'User backup';
Expand Down
47 changes: 47 additions & 0 deletions lib/coursecatlib.php
Original file line number Diff line number Diff line change
Expand Up @@ -2058,6 +2058,53 @@ public function get_course_contacts() {
return $this->coursecontacts;
}

/**
* Checks if course has any associated overview files
*
* @return bool
*/
public function has_course_overviewfiles() {
global $CFG;
if (empty($CFG->courseoverviewfileslimit)) {
return 0;
}
require_once($CFG->libdir. '/filestorage/file_storage.php');
$fs = get_file_storage();
$context = context_course::instance($this->id);
return $fs->is_area_empty($context->id, 'course', 'overviewfiles');
}

/**
* Returns all course overview files
*
* @return array array of stored_file objects
*/
public function get_course_overviewfiles() {
global $CFG;
if (empty($CFG->courseoverviewfileslimit)) {
return array();
}
require_once($CFG->libdir. '/filestorage/file_storage.php');
$fs = get_file_storage();
$context = context_course::instance($this->id);
$files = $fs->get_area_files($context->id, 'course', 'overviewfiles', false, 'filename', false);
if (count($files)) {
$overviewfilesoptions = course_overviewfiles_options($this->id);
$acceptedtypes = $overviewfilesoptions['accepted_types'];
if ($acceptedtypes !== '*') {
// filter only files with allowed extensions
require_once($CFG->libdir. '/filelib.php');
$files = array_filter($files, function ($file) use ($acceptedtypes) {
return file_extension_in_typegroup($file->get_filename(), $acceptedtypes);} );
}
if (count($files) > $CFG->courseoverviewfileslimit) {
// return no more than $CFG->courseoverviewfileslimit files
$files = array_slice($files, 0, $CFG->courseoverviewfileslimit, true);
}
}
return $files;
}

// ====== magic methods =======

public function __isset($name) {
Expand Down
35 changes: 35 additions & 0 deletions lib/filebrowser/file_info_context_course.php
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,40 @@ protected function get_area_course_summary($itemid, $filepath, $filename) {
return new file_info_stored($this->browser, $this->context, $storedfile, $urlbase, get_string('areacourseintro', 'repository'), false, true, true, false);
}

/**
* Gets a stored file for the course images filearea directory
*
* @param int $itemid item ID
* @param string $filepath file path
* @param string $filename file name
* @return file_info|null file_info instance or null if not found or access not allowed
*/
protected function get_area_course_overviewfiles($itemid, $filepath, $filename) {
global $CFG;

if (!has_capability('moodle/course:update', $this->context)) {
return null;
}
if (is_null($itemid)) {
return $this;
}

$fs = get_file_storage();

$filepath = is_null($filepath) ? '/' : $filepath;
$filename = is_null($filename) ? '.' : $filename;
if (!$storedfile = $fs->get_file($this->context->id, 'course', 'overviewfiles', 0, $filepath, $filename)) {
if ($filepath === '/' and $filename === '.') {
$storedfile = new virtual_root_file($this->context->id, 'course', 'overviewfiles', 0);
} else {
// not found
return null;
}
}
$urlbase = $CFG->wwwroot.'/pluginfile.php';
return new file_info_stored($this->browser, $this->context, $storedfile, $urlbase, get_string('areacourseoverviewfiles', 'repository'), false, true, true, false);
}

/**
* Gets a stored file for the course section filearea directory
*
Expand Down Expand Up @@ -365,6 +399,7 @@ public function get_children() {
private function get_filtered_children($extensions = '*', $countonly = false, $returnemptyfolders = false) {
$areas = array(
array('course', 'summary'),
array('course', 'overviewfiles'),
array('course', 'section'),
array('backup', 'section'),
array('backup', 'course'),
Expand Down
4 changes: 2 additions & 2 deletions lib/filelib.php
Original file line number Diff line number Diff line change
Expand Up @@ -4075,14 +4075,14 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) {
send_file_not_found();
}

if ($filearea === 'summary') {
if ($filearea === 'summary' || $filearea === 'overviewfiles') {
if ($CFG->forcelogin) {
require_login();
}

$filename = array_pop($args);
$filepath = $args ? '/'.implode('/', $args).'/' : '/';
if (!$file = $fs->get_file($context->id, 'course', 'summary', 0, $filepath, $filename) or $file->is_directory()) {
if (!$file = $fs->get_file($context->id, 'course', $filearea, 0, $filepath, $filename) or $file->is_directory()) {
send_file_not_found();
}

Expand Down
9 changes: 7 additions & 2 deletions theme/base/style/course.css
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,9 @@ li.section.hidden span.commands a.editing_show {cursor:default;}
.coursebox .name a {display:block;background-image:url([[pix:moodle|i/course]]);background-repeat: no-repeat;padding-left:21px;background-position: center left;}
.coursebox.remotehost .name a {background-image:url([[pix:moodle|i/mnethost]]);}
.coursebox .name,
.coursebox .teachers {float:left;width: 40%;}
.coursebox .teachers,
.coursebox .content .courseimage,
.coursebox .content .coursefile {float:left;width:40%;clear:left;}
.coursebox .teachers li {list-style-type:none;padding:0;margin:0;}
.coursebox .enrolmenticons {padding:3px 0;float:right;}
.coursebox .moreinfo {padding:3px 0;float:right;}
Expand All @@ -127,10 +129,13 @@ li.section.hidden span.commands a.editing_show {cursor:default;}
.coursebox .coursecat {float:right;width: 55%;}
.coursebox .coursecat {text-align:right;clear:right;}
.coursebox.remotecoursebox .remotecourseinfo {float:left;width: 40%;}
.coursebox .content .courseimage img {max-width:100px;max-height:100px;}

.dir-rtl .coursebox .name a {padding-left:0;padding-right:21px;background-position: center right;}
.dir-rtl .coursebox .name,
.dir-rtl .coursebox .teachers {float:right;}
.dir-rtl .coursebox .teachers,
.dir-rtl .coursebox .content .courseimage,
.dir-rtl .coursebox .content .coursefile {float:right;clear:right;}
.dir-rtl .coursebox .enrolmenticons,
.dir-rtl .coursebox .moreinfo {float:left;}
.dir-rtl .coursebox .summary,
Expand Down
4 changes: 3 additions & 1 deletion theme/formal_white/style/course.css
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
.coursebox .content {font-size:90%;}
.coursebox .teachers {margin:5px 1em;}
.coursebox .summary,
.coursebox .coursecat {margin:5px;}
.coursebox .coursecat,
.coursebox .content .courseimage,
.coursebox .content .coursefile {margin:5px;}
.coursebox > .content:after,
.coursebox > .info:after {clear:both;content:".";display:block;height:0;min-width:0;visibility:hidden;}

Expand Down
16 changes: 13 additions & 3 deletions theme/magazine/style/core.css
Original file line number Diff line number Diff line change
Expand Up @@ -915,15 +915,25 @@ div.coursebox h3.name a {
padding-left: 5px;
}

.dir-rtl .coursebox ul.teachers {
.coursebox .content .courseimage,
.coursebox .content .coursefile {
padding-left: 5px;
}

.dir-rtl .coursebox ul.teachers,
.dir-rtl .coursebox .content .courseimage,
.dir-rtl .coursebox .content .coursefile {
padding-right: 5px;
}

.coursebox ul.teachers li {
.coursebox ul.teachers li,
.coursebox .coursecat {
font-size: 10px;
}

.coursebox ul.teachers li a {
.coursebox ul.teachers li a,
.coursebox .coursecat a,
.coursebox .content .coursefile a {
font-size: 11px;
}

Expand Down
Loading

0 comments on commit d1f8c1b

Please sign in to comment.