Enables viewing sections by name and allows formatters to customize behavior.

From: Brandon Turner <brandont@thinkwell.com>

This patch enables viewing sections by name across various areas of moodle and
allows course formats to customize this behavior through the use of a callback
function.

When a section name needs to be printed, the developer should call the
get_section_name function in /course/lib.php.  By default, this function
returns the appropriately formatted section name for the current course format
(e.g. "Topic 4").  If the section uses a custom name, that name is returned
instead (e.g. Intro to Calculus).

Course formatters can override the default behavior by implementing the
callback_xxx_get_section_name function in their lib.php file (where xxx is the
name of the course format).  This callback is also used by the navigation
system.
---
 course/editsection.php             |   13 ++-------
 course/lib.php                     |   52 ++++++++++++++++++++++++++++++++++--
 course/modedit.php                 |    8 +++---
 course/recent.php                  |    9 +-----
 course/recent_form.php             |    9 ++----
 course/report/outline/index.php    |   10 ++-----
 course/user.php                    |    8 +-----
 mod/assignment/type/online/all.php |   21 ++-------------
 mod/forum/discuss.php              |   11 +++-----
 mod/quiz/index.php                 |    9 +++---
 10 files changed, 77 insertions(+), 73 deletions(-)

diff --git a/course/editsection.php b/course/editsection.php
index b44072d..dc5c4f6 100644
--- a/course/editsection.php
+++ b/course/editsection.php
@@ -66,16 +66,9 @@ if ($mform->is_cancelled()){
     redirect("view.php?id=$course->id");
 }
 
-/// Inelegant hack for bug 3408
-if ($course->format == 'site') {
-    $sectionname  = get_string('site');
-    $stredit      = get_string('edita', '', " $sectionname");
-    $strsummaryof = get_string('summaryof', '', " $sectionname");
-} else {
-    $sectionname  = get_section_name($course->format);
-    $stredit      = get_string('edita', '', " $sectionname $section->section");
-    $strsummaryof = get_string('summaryof', '', " $sectionname $section->section");
-}
+$sectionname  = get_section_name($course->format, $course, $section);
+$stredit      = get_string('edita', '', " $sectionname");
+$strsummaryof = get_string('summaryof', '', " $sectionname");
 
 $PAGE->set_title($stredit);
 $PAGE->set_heading($course->fullname);
diff --git a/course/lib.php b/course/lib.php
index 1f257d6..ccf9016 100644
--- a/course/lib.php
+++ b/course/lib.php
@@ -3241,13 +3241,59 @@ function move_category($category, $newparentcat) {
 }
 
 /**
+ * Returns the display name of the given section that the course prefers.
+ *
+ * This function utilizes a callback that can be implemented within the course
+ * formats lib.php file to customize the display name that is used to reference
+ * the section.
+ *
+ * By default (if callback is not defined) the method
+ * {@see get_numeric_section_name} is called instead.
+ *
+ * @param string $format Course format ID e.g. 'weeks'
+ * @param stdClass $course
+ * @param stdClass $section Section object from database
+ * @param array $sections Array of all sections
+ * @return Display name that the course format prefers, e.g. "Week 2"
+ *
+ * @see get_generic_section_name
+ */
+function get_section_name($format, stdClass $course, stdClass $section, $sections=null) {
+    global $CFG;
+
+    /// Inelegant hack for bug 3408
+    if ($format == 'site') {
+        return get_string('site');
+    }
+
+    // Use course formatter callback if it exists
+    $namingfile = $CFG->dirroot.'/course/format/'.$format.'/lib.php';
+    $namingfunction = 'callback_'.$format.'_get_section_name';
+    if (!function_exists($namingfunction) && file_exists($namingfile)) {
+        require_once $namingfile;
+    }
+    if (function_exists($namingfunction)) {
+        if ($sections === null) {
+            $sections = get_all_sections($course->id);
+        }
+        return $namingfunction($course, $section, $sections);
+    }
+
+    // else, default behavior:
+    return get_generic_section_name($format, $course, $section);
+}
+
+/**
  * @param string $format Course format ID e.g. 'weeks'
- * @return Name that the course format prefers for sections
+ * @param stdClass $course
+ * @param stdClass $section Section object from database
+ * @return Display name that the course format prefers, e.g. "Week 2"
  */
-function get_section_name($format) {
-    return get_string('sectionname', "format_$format");
+function get_generic_section_name($format, stdClass $course, stdClass $section) {
+    return get_string('sectionname', "format_$format") . ' ' . $section->section;
 }
 
+
 /**
  * Can the current user delete this course?
  * Course creators have exception,
diff --git a/course/modedit.php b/course/modedit.php
index fbf5c21..e17ccc9 100644
--- a/course/modedit.php
+++ b/course/modedit.php
@@ -87,13 +87,13 @@ if (!empty($add)) {
         $data->type = $type;
     }
 
-    $sectionname = get_section_name($course->format);
+    $sectionname = get_section_name($course->format, $course, $cw);
     $fullmodulename = get_string('modulename', $module->name);
 
     if ($data->section && $course->format != 'site') {
         $heading = new object();
         $heading->what = $fullmodulename;
-        $heading->to   = "$sectionname $data->section";
+        $heading->to   = $sectionname;
         $pageheading = get_string('addinganewto', 'moodle', $heading);
     } else {
         $pageheading = get_string('addinganew', 'moodle', $fullmodulename);
@@ -172,13 +172,13 @@ if (!empty($add)) {
         }
     }
 
-    $sectionname = get_section_name($course->format);
+    $sectionname = get_section_name($course->format, $course, $cw);
     $fullmodulename = get_string('modulename', $module->name);
 
     if ($data->section && $course->format != 'site') {
         $heading = new object();
         $heading->what = $fullmodulename;
-        $heading->in   = "$sectionname $cw->section";
+        $heading->in   = $sectionname;
         $pageheading = get_string('updatingain', 'moodle', $heading);
     } else {
         $pageheading = get_string('updatinga', 'moodle', $fullmodulename);
diff --git a/course/recent.php b/course/recent.php
index fc05619..eced137 100644
--- a/course/recent.php
+++ b/course/recent.php
@@ -91,7 +91,7 @@ if (has_capability('moodle/course:viewhiddensections', $context)) {
     $hiddenfilter = "AND cs.visible = 1";
 }
 $sections = array();
-if ($ss = $DB->get_records_sql("SELECT cs.id, cs.section, cs.sequence, cs.summary, cs.visible
+if ($ss = $DB->get_records_sql("SELECT cs.id, cs.section, cs.sequence, cs.name, cs.summary, cs.visible
                                   FROM {course_sections} cs
                                  WHERE cs.course = ? AND cs.section <= ?
                                        $hiddenfilter
@@ -122,11 +122,6 @@ if ($param->modid === 'all') {
     $sections = array($section->sequence=>$section);
 }
 
-switch ($course->format) {
-    case 'weeks':  $sectiontitle = get_string('week'); break;
-    case 'topics': $sectiontitle = get_string('topic'); break;
-    default: $sectiontitle = get_string('section'); break;
-}
 
 if (is_null($modinfo->groups)) {
     $modinfo->groups = groups_get_user_groups($course->id); // load all my groups and cache it in modinfo
@@ -140,7 +135,7 @@ foreach ($sections as $section) {
     $activity = new object();
     $activity->type = 'section';
     if ($section->section > 0) {
-        $activity->name = $sectiontitle.' '.$section->section;
+        $activity->name = get_section_name($course->format, $course, $section, $sections);
     } else {
         $activity->name = '';
     }
diff --git a/course/recent_form.php b/course/recent_form.php
index 9424263..d618289 100644
--- a/course/recent_form.php
+++ b/course/recent_form.php
@@ -36,6 +36,7 @@ class recent_form extends moodleform {
         $mform =& $this->_form;
         $context = get_context_instance(CONTEXT_COURSE, $COURSE->id);
         $modinfo = get_fast_modinfo($COURSE);
+        $sections = get_all_sections($COURSE->id);
 
         $mform->addElement('header', 'filters', get_string('managefilters')); //TODO: add better string
 
@@ -70,11 +71,7 @@ class recent_form extends moodleform {
             $mform->setAdvanced('user');
         }
 
-        switch ($COURSE->format) {
-            case 'weeks':  $sectiontitle = get_string('week'); break;
-            case 'topics': $sectiontitle = get_string('topic'); break;
-            default: $sectiontitle = get_string('section'); break;
-        }
+        $sectiontitle = get_string('sectionname', 'format_'.$COURSE->format);
 
         $options = array(''=>get_string('allactivities'));
         $modsused = array();
@@ -102,7 +99,7 @@ class recent_form extends moodleform {
         }
 
         foreach ($modinfo->sections as $section=>$cmids) {
-            $options["section/$section"] = "-- $sectiontitle $section --";
+            $options["section/$section"] = "-- ".get_section_name($COURSE->format, $COURSE, $sections[$section], $sections)." --";
             foreach ($cmids as $cmid) {
                 $cm = $modinfo->cms[$cmid];
                 if (empty($modsused[$cm->modname]) or !$cm->uservisible) {
diff --git a/course/report/outline/index.php b/course/report/outline/index.php
index eef520c..33a9a38 100644
--- a/course/report/outline/index.php
+++ b/course/report/outline/index.php
@@ -60,6 +60,7 @@
     }
 
     $modinfo = get_fast_modinfo($course);
+    $sections = get_all_sections($course->id);
 
     $sql = "SELECT cm.id, COUNT('x') AS numviews, MAX(time) AS lasttime
               FROM {course_modules} cm
@@ -85,14 +86,9 @@
                 $sectioncell = new html_table_cell();
                 $sectioncell->colspan = count($outlinetable->head);
 
-                $sectiontitle = '';
-                switch ($course->format) {
-                    case 'weeks': $sectiontitle = get_string('week'); break;
-                    case 'topics': $sectiontitle = get_string('topic'); break;
-                    default: $sectiontitle = get_string('section'); break;
-                }
+                $sectiontitle = get_section_name($course->format, $course, $sections[$sectionnum], $sections);
 
-                $sectioncell->text = $OUTPUT->heading($sectiontitle . ' ' . $sectionnum, 3);
+                $sectioncell->text = $OUTPUT->heading($sectiontitle, 3);
                 $sectionrow->cells[] = $sectioncell;
                 $outlinetable->data[] = $sectionrow;
 
diff --git a/course/user.php b/course/user.php
index 24821d9..82529ef 100644
--- a/course/user.php
+++ b/course/user.php
@@ -280,12 +280,8 @@ switch ($mode) {
                     if ($section->sequence) {
                         echo '<div class="section">';
                         echo '<h2>';
-                        switch ($course->format) {
-                            case "weeks": print_string("week"); break;
-                            case "topics": print_string("topic"); break;
-                            default: print_string("section"); break;
-                        }
-                        echo " $i</h2>";
+                        echo get_section_name($course->format, $course, $section, $sections);
+                        echo "</h2>";
 
                         echo '<div class="content">';
 
diff --git a/mod/assignment/type/online/all.php b/mod/assignment/type/online/all.php
index 3c8a670..e4a6126 100644
--- a/mod/assignment/type/online/all.php
+++ b/mod/assignment/type/online/all.php
@@ -40,8 +40,6 @@ $str->emptysubmission = get_string('emptysubmission','assignment');
 $str->noassignments = get_string('noassignments','assignment');
 $str->onlinetext = get_string('typeonline','assignment');
 $str->submitted = get_string('submitted','assignment');
-$str->topic = get_string('topic');
-$str->week = get_string('week');
 
 $PAGE->navbar->add($str->assignments, new moodle_url('/mod/assignment/index.php', array('id'=>$id)));
 $PAGE->navbar->add($str->onlinetext);
@@ -49,16 +47,7 @@ $PAGE->navbar->add($str->onlinetext);
 // get all the assignments in the course
 $assignments = get_all_instances_in_course('assignment',$course, $USER->id );
 
-// get correct text for course type
-if ($course->format=='weeks') {
-    $courseformat = $str->week;
-
-} else if ($course->format=='topics') {
-    $courseformat = $str->topic;
-
-} else {
-    $courseformat = '';
-}
+$sections = get_all_sections($course->id);
 
 // array to hold display data
 $views = array();
@@ -109,11 +98,7 @@ foreach( $assignments as $assignment ) {
     $view = new stdClass;
 
     // start to build view object
-    if (!empty($courseformat)) {
-        $view->section = "$courseformat {$assignment->section}";
-    } else {
-        $view->section = '';
-    }
+    $view->section = get_section_name($course->format, $course, $sections[$assignment->section], $sections);
 
     $view->name = $assignment->name;
     $view->submitted = $submitted;
@@ -159,4 +144,4 @@ foreach ($views as $view) {
     echo $OUTPUT->container_end();
 }
 
-echo $OUTPUT->footer();
\ No newline at end of file
+echo $OUTPUT->footer();
diff --git a/mod/forum/discuss.php b/mod/forum/discuss.php
index e6dd2ea..d773567 100644
--- a/mod/forum/discuss.php
+++ b/mod/forum/discuss.php
@@ -231,12 +231,8 @@
         // single discussion forum can't be moved.
         $modinfo = get_fast_modinfo($course);
         if (isset($modinfo->instances['forum'])) {
-            if ($course->format == 'weeks') {
-                $strsection = get_string("week");
-            } else {
-                $strsection = get_string("topic");
-            }
             $forummenu = array();
+            $sections = get_all_sections($course->id);
             foreach ($modinfo->instances['forum'] as $forumcm) {
                 if (!$forumcm->uservisible || !has_capability('mod/forum:startdiscussion',
                     get_context_instance(CONTEXT_MODULE,$forumcm->id))) {
@@ -244,12 +240,13 @@
                 }
 
                 $section = $forumcm->sectionnum;
+                $sectionname = get_section_name($course->format, $course, $sections[$section], $sections);
                 if (empty($forummenu[$section])) {
-                    $forummenu[$section] = array("$strsection $section" => array());
+                    $forummenu[$section] = array($sectionname => array());
                 }
                 if ($forumcm->instance != $forum->id) {
                     $url = "/mod/forum/discuss.php?d=$discussion->id&move=$forumcm->instance&sesskey=".sesskey();
-                    $forummenu[$section]["$strsection $section"][$url] = format_string($forumcm->name);
+                    $forummenu[$section][$sectionname][$url] = format_string($forumcm->name);
                 }
             }
             if (!empty($forummenu)) {
diff --git a/mod/quiz/index.php b/mod/quiz/index.php
index cf5dbbd..4552cf8 100644
--- a/mod/quiz/index.php
+++ b/mod/quiz/index.php
@@ -44,6 +44,7 @@
         notice(get_string('thereareno', 'moodle', $strquizzes), "../../course/view.php?id=$course->id");
         die;
     }
+    $sections = get_all_sections($course->id);
 
 // Check if we need the closing date header
     $showclosingheader = false;
@@ -69,11 +70,7 @@
         array_push($align, 'left');
     }
 
-    if ($course->format == 'weeks' or $course->format == 'weekscss') {
-        array_unshift($headings, get_string('week'));
-    } else {
-        array_unshift($headings, get_string('section'));
-    }
+    array_unshift($headings, get_string('sectionname', 'format_'.$course->format));
     array_unshift($align, 'center');
 
     $showing = '';  // default
@@ -103,6 +100,7 @@
     $table->head = $headings;
     $table->align = $align;
 
+
 /// Populate the table with the list of instances.
     $currentsection = '';
     foreach ($quizzes as $quiz) {
@@ -115,6 +113,7 @@
         if ($quiz->section != $currentsection) {
             if ($quiz->section) {
                 $strsection = $quiz->section;
+                $strsection = get_section_name($course->format, $course, $sections[$quiz->section], $sections);
             }
             if ($currentsection) {
                 $learningtable->data[] = 'hr';
