From aea2e3c30df13d303eb09495cca2fd389bfae20a Mon Sep 17 00:00:00 2001 From: Marina Glancy Date: Tue, 16 Oct 2012 12:02:56 +0800 Subject: [PATCH] MDL-35768 Allow caching of section format options in course.sectioncache --- course/format/lib.php | 38 +++++++++++++++++++++++++++++++------- lib/modinfolib.php | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 7 deletions(-) diff --git a/course/format/lib.php b/course/format/lib.php index f79db1737b8..f4f785c959d 100644 --- a/course/format/lib.php +++ b/course/format/lib.php @@ -446,9 +446,12 @@ abstract class format_base { * course edit form, it may even make sence to use special prefix for them. * * Each option must have the option name as a key and the array of properties as a value: - * 'default' - default value for this option - * 'label' - localised human-readable label for the edit form + * 'default' - default value for this option (assumed null if not specified) * 'type' - type of the option value (PARAM_INT, PARAM_RAW, etc.) + * + * Additional properties used by default implementation of + * {@link format_base::create_edit_form_elements()} (calls this method with $foreditform = true) + * 'label' - localised human-readable label for the edit form * 'element_type' - type of the form element, default 'text' * 'element_attributes' - additional attributes for the form element, these are 4th and further * arguments in the moodleform::addElement() method @@ -457,13 +460,16 @@ abstract class format_base { * 'help_component' - language component to look for help string, by default this the component * for this course format * - * Note that all properties except 'default' and 'type' are used only in - * {@link format_base::create_edit_form_elements()}, which calls this function with the - * argument $foreditform = true - * * This is an interface for creating simple form elements. If format plugin wants to use other * methods such as disableIf, it can be done by overriding create_edit_form_elements(). * + * Course format options can be accessed as: + * $this->get_course()->OPTIONNAME (inside the format class) + * course_get_format($course)->get_course()->OPTIONNAME (outside of format class) + * + * All course options are returned by calling: + * $this->get_format_options(); + * * @param bool $foreditform * @return array of options */ @@ -481,6 +487,18 @@ abstract class format_base { * is recommended to be set only for fields used in {@link format_base::get_section_name()}, * {@link format_base::extend_course_navigation()} and {@link format_base::get_view_url()} * + * For better performance cached options are recommended to have 'cachedefault' property + * Unlike 'default', 'cachedefault' should be static and not access get_config(). + * + * Regardless of value of 'cache' all options are accessed in the code as + * $sectioninfo->OPTIONNAME + * where $sectioninfo is instance of section_info, returned by + * get_fast_modinfo($course)->get_section_info($sectionnum) + * or get_fast_modinfo($course)->get_section_info_all() + * + * All format options for particular section are returned by calling: + * $this->get_format_options($section); + * * @param bool $foreditform * @return array */ @@ -491,6 +509,10 @@ abstract class format_base { /** * Returns the format options stored for this course or course section * + * When overriding please note that this function is called from rebuild_course_cache() + * and section_info object, therefore using of get_fast_modinfo() and/or any function that + * accesses it may lead to recursion. + * * @param null|int|stdClass|section_info $section if null the course format options will be returned * otherwise options for specified section will be returned. This can be either * section object or relative section number (field course_sections.section) @@ -513,7 +535,9 @@ abstract class format_base { } else if ($this->courseid && isset($section->id)) { // course section format options will be returned $sectionid = $section->id; - } else if ($this->courseid && is_int($section) && ($sectionobj = $this->get_section($section))) { + } else if ($this->courseid && is_int($section) && + ($sectionobj = $DB->get_record('course_sections', + array('section' => $section, 'courseid' => $this->courseid), 'id'))) { // course section format options will be returned $sectionid = $sectionobj->id; } else { diff --git a/lib/modinfolib.php b/lib/modinfolib.php index 4f36e2d69a9..ec02959e928 100644 --- a/lib/modinfolib.php +++ b/lib/modinfolib.php @@ -364,8 +364,18 @@ class course_modinfo extends stdClass { 'availablefrom, availableuntil, showavailability, groupingid'); $compressedsections = array(); + $formatoptionsdef = course_get_format($courseid)->section_format_options(); // Remove unnecessary data and add availability foreach ($sections as $number => $section) { + // Add cached options from course format to $section object + foreach ($formatoptionsdef as $key => $option) { + if (!empty($option['cache'])) { + $formatoptions = course_get_format($courseid)->get_format_options($section); + if (!array_key_exists('cachedefault', $option) || $option['cachedefault'] !== $formatoptions[$key]) { + $section->$key = $formatoptions[$key]; + } + } + } // Clone just in case it is reused elsewhere $compressedsections[$number] = clone($section); section_info::convert_for_section_cache($compressedsections[$number]); @@ -1568,6 +1578,13 @@ class section_info implements IteratorAggregate { 'groupingid' => '0', ); + /** + * Stores format options that have been cached when building 'coursecache' + * When the format option is requested we look first if it has been cached + * @var array + */ + private $cachedformatoptions = array(); + /** * Constructs object from database information plus extra required data. * @param object $data Array entry from cached sectioncache @@ -1597,6 +1614,18 @@ class section_info implements IteratorAggregate { } } + // cached course format data + $formatoptionsdef = course_get_format($courseid)->section_format_options(); + foreach ($formatoptionsdef as $field => $option) { + if (!empty($option['cache'])) { + if (isset($data->{$field})) { + $this->cachedformatoptions[$field] = $data->{$field}; + } else if (array_key_exists('cachedefault', $option)) { + $this->cachedformatoptions[$field] = $option['cachedefault']; + } + } + } + // Other data from other places $this->_course = $courseid; $this->_section = $number; @@ -1675,6 +1704,9 @@ class section_info implements IteratorAggregate { if (property_exists($this, '_'.$name)) { return $this->{'_'.$name}; } + if (array_key_exists($name, $this->cachedformatoptions)) { + return $this->cachedformatoptions[$name]; + } $defaultformatoptions = course_get_format($this->_course)->section_format_options(); // precheck if the option is defined in format to avoid unnecessary DB queries in get_format_options() if (array_key_exists($name, $defaultformatoptions)) {