From 9ca0420e931fe877f33af54297f973c3beccaee3 Mon Sep 17 00:00:00 2001 From: Marina Glancy Date: Mon, 4 Apr 2016 08:57:09 +0800 Subject: [PATCH] MDL-45064 course: mod callback get_shortcuts() also deprecate callback get_types() --- course/format/singleactivity/lib.php | 14 ++- course/lib.php | 126 +++++++++++++++------------ course/renderer.php | 49 ++--------- lang/en/moodle.php | 1 + lib/moodlelib.php | 6 +- mod/upgrade.txt | 2 + 6 files changed, 99 insertions(+), 99 deletions(-) diff --git a/course/format/singleactivity/lib.php b/course/format/singleactivity/lib.php index 813e2c62c1c..f803e5985cc 100644 --- a/course/format/singleactivity/lib.php +++ b/course/format/singleactivity/lib.php @@ -341,7 +341,9 @@ class format_singleactivity extends format_base { } /** - * Checks if the activity type requires subtypes. + * Checks if the activity type has multiple items in the activity chooser. + * This may happen as a result of defining callback modulename_get_shortcuts() + * or [deprecated] modulename_get_types() - TODO MDL-53697 remove this line. * * @return bool|null (null if the check is not possible) */ @@ -349,7 +351,13 @@ class format_singleactivity extends format_base { if (!($modname = $this->get_activitytype())) { return null; } - return component_callback('mod_' . $modname, 'get_types', array(), MOD_SUBTYPE_NO_CHILDREN) !== MOD_SUBTYPE_NO_CHILDREN; + $metadata = get_module_metadata($this->get_course(), self::get_supported_activities()); + foreach ($metadata as $key => $moduledata) { + if (preg_match('/^'.$modname.':/', $key)) { + return true; + } + } + return false; } /** @@ -399,7 +407,7 @@ class format_singleactivity extends format_base { if ($this->can_add_activity()) { // This is a user who has capability to create an activity. if ($this->activity_has_subtypes()) { - // Activity that requires subtype can not be added automatically. + // Activity has multiple items in the activity chooser, it can not be added automatically. if (optional_param('addactivity', 0, PARAM_INT)) { return; } else { diff --git a/course/lib.php b/course/lib.php index bbc0eb1b288..9307e3c60ee 100644 --- a/course/lib.php +++ b/course/lib.php @@ -1226,7 +1226,7 @@ function set_section_visible($courseid, $sectionnumber, $visibility) { * module */ function get_module_metadata($course, $modnames, $sectionreturn = null) { - global $CFG, $OUTPUT; + global $OUTPUT; // get_module_metadata will be called once per section on the page and courses may show // different modules to one another @@ -1246,91 +1246,107 @@ function get_module_metadata($course, $modnames, $sectionreturn = null) { } if (isset($modlist[$course->id][$modname])) { // This module is already cached - $return[$modname] = $modlist[$course->id][$modname]; + $return += $modlist[$course->id][$modname]; continue; } + $modlist[$course->id][$modname] = array(); - // Include the module lib - $libfile = "$CFG->dirroot/mod/$modname/lib.php"; - if (!file_exists($libfile)) { - continue; - } - include_once($libfile); - - $aliases = component_callback($modname, 'get_aliases', array(), array()); - if (count($aliases) > 0) { - foreach ($aliases as $alias) { - $module = $alias; - $module->archetype = plugin_supports('mod', $modname, FEATURE_MOD_ARCHETYPE, MOD_ARCHETYPE_OTHER); - $return[$alias->name] = $module; + // Create an object for a default representation of this module type in the activity chooser. It will be used + // if module does not implement callback get_shortcuts() and it will also be passed to the callback if it exists. + $defaultmodule = new stdClass(); + $defaultmodule->title = $modnamestr; + $defaultmodule->name = $modname; + $defaultmodule->link = new moodle_url($urlbase, array('add' => $modname)); + $defaultmodule->icon = $OUTPUT->pix_icon('icon', '', $defaultmodule->name, array('class' => 'icon')); + $sm = get_string_manager(); + if ($sm->string_exists('modulename_help', $modname)) { + $defaultmodule->help = get_string('modulename_help', $modname); + if ($sm->string_exists('modulename_link', $modname)) { // Link to further info in Moodle docs. + $link = get_string('modulename_link', $modname); + $linktext = get_string('morehelp'); + $defaultmodule->help .= html_writer::tag('div', + $OUTPUT->doc_link($link, $linktext, true), array('class' => 'helpdoclink')); } } + $defaultmodule->archetype = plugin_supports('mod', $modname, FEATURE_MOD_ARCHETYPE, MOD_ARCHETYPE_OTHER); - // NOTE: this is legacy stuff, module subtypes are very strongly discouraged!! - $gettypesfunc = $modname.'_get_types'; - $types = MOD_SUBTYPE_NO_CHILDREN; - if (function_exists($gettypesfunc)) { - $types = $gettypesfunc(); + // Legacy support for callback get_types() - do not use any more, use get_shortcuts() instead! + $typescallbackexists = component_callback_exists($modname, 'get_types'); + + // Each module can implement callback modulename_get_shortcuts() in its lib.php and return the list + // of elements to be added to activity chooser. + $items = component_callback($modname, 'get_shortcuts', array($defaultmodule), null); + if ($items !== null) { + foreach ($items as $item) { + // Add all items to the return array. All items must have different links, use them as a key in the return array. + if (!isset($item->archetype)) { + $item->archetype = $defaultmodule->archetype; + } + if (!isset($item->icon)) { + $item->icon = $defaultmodule->icon; + } + // If plugin returned the only one item with the same link as default item - cache it as $modname, + // otherwise append the link url to the module name. + $item->name = (count($items) == 1 && + $item->link->out() === $defaultmodule->link->out()) ? $modname : $modname . ':' . $item->link; + $modlist[$course->id][$modname][$item->name] = $item; + } + $return += $modlist[$course->id][$modname]; + if ($typescallbackexists) { + debugging('Both callbacks get_shortcuts() and get_types() are found in module ' . $modname . + '. Callback get_types() will be completely ignored', DEBUG_DEVELOPER); + } + // If get_shortcuts() callback is defined, the default module action is not added. + // It is a responsibility of the callback to add it to the return value unless it is not needed. + continue; } + + if ($typescallbackexists) { + debugging('Callback get_types() is found in module ' . $modname . ', this functionality is deprecated, ' . + 'please use callback get_shortcuts() instead', DEBUG_DEVELOPER); + } + $types = component_callback($modname, 'get_types', array(), MOD_SUBTYPE_NO_CHILDREN); if ($types !== MOD_SUBTYPE_NO_CHILDREN) { + // Legacy support for deprecated callback get_types(). To be removed in Moodle 3.5. TODO MDL-53697. if (is_array($types) && count($types) > 0) { - $group = new stdClass(); - $group->name = $modname; - $group->icon = $OUTPUT->pix_icon('icon', '', $modname, array('class' => 'icon')); + $grouptitle = $modnamestr; + $icon = $OUTPUT->pix_icon('icon', '', $modname, array('class' => 'icon')); foreach($types as $type) { if ($type->typestr === '--') { continue; } if (strpos($type->typestr, '--') === 0) { - $group->title = str_replace('--', '', $type->typestr); + $grouptitle = str_replace('--', '', $type->typestr); continue; } - // Set the Sub Type metadata + // Set the Sub Type metadata. $subtype = new stdClass(); - $subtype->title = $type->typestr; + $subtype->title = get_string('activitytypetitle', '', + (object)['activity' => $grouptitle, 'type' => $type->typestr]); $subtype->type = str_replace('&', '&', $type->type); - $subtype->name = preg_replace('/.*type=/', '', $subtype->type); + $typename = preg_replace('/.*type=/', '', $subtype->type); $subtype->archetype = $type->modclass; - // The group archetype should match the subtype archetypes and all subtypes - // should have the same archetype - $group->archetype = $subtype->archetype; - if (!empty($type->help)) { $subtype->help = $type->help; } else if (get_string_manager()->string_exists('help' . $subtype->name, $modname)) { $subtype->help = get_string('help' . $subtype->name, $modname); } - $subtype->link = new moodle_url($urlbase, array('add' => $modname, 'type' => $subtype->name)); - $group->types[] = $subtype; + $subtype->link = new moodle_url($urlbase, array('add' => $modname, 'type' => $typename)); + $subtype->name = $modname . ':' . $subtype->link; + $subtype->icon = $icon; + $modlist[$course->id][$modname][$subtype->name] = $subtype; } - $modlist[$course->id][$modname] = $group; + $return += $modlist[$course->id][$modname]; } } else { - $module = new stdClass(); - $module->title = $modnamestr; - $module->name = $modname; - $module->link = new moodle_url($urlbase, array('add' => $modname)); - $module->icon = $OUTPUT->pix_icon('icon', '', $module->name, array('class' => 'icon')); - $sm = get_string_manager(); - if ($sm->string_exists('modulename_help', $modname)) { - $module->help = get_string('modulename_help', $modname); - if ($sm->string_exists('modulename_link', $modname)) { // Link to further info in Moodle docs - $link = get_string('modulename_link', $modname); - $linktext = get_string('morehelp'); - $module->help .= html_writer::tag('div', $OUTPUT->doc_link($link, $linktext, true), array('class' => 'helpdoclink')); - } - } - $module->archetype = plugin_supports('mod', $modname, FEATURE_MOD_ARCHETYPE, MOD_ARCHETYPE_OTHER); - $modlist[$course->id][$modname] = $module; - } - if (isset($modlist[$course->id][$modname])) { - $return[$modname] = $modlist[$course->id][$modname]; - } else { - debugging("Invalid module metadata configuration for {$modname}"); + // Neither get_shortcuts() nor get_types() callbacks found, use the default item for the activity chooser. + $modlist[$course->id][$modname][$modname] = $defaultmodule; + $return[$modname] = $defaultmodule; } } + core_collator::asort_objects_by_property($return, 'title'); return $return; } diff --git a/course/renderer.php b/course/renderer.php index 617f4e81315..787866a4853 100644 --- a/course/renderer.php +++ b/course/renderer.php @@ -252,14 +252,7 @@ class core_course_renderer extends plugin_renderer_base { protected function course_modchooser_module_types($modules) { $return = ''; foreach ($modules as $module) { - if (!isset($module->types)) { - $return .= $this->course_modchooser_module($module); - } else { - $return .= $this->course_modchooser_module($module, array('nonoption')); - foreach ($module->types as $type) { - $return .= $this->course_modchooser_module($type, array('option', 'subtype')); - } - } + $return .= $this->course_modchooser_module($module); } return $return; } @@ -443,39 +436,15 @@ class core_course_renderer extends plugin_renderer_base { $activities = array(MOD_CLASS_ACTIVITY => array(), MOD_CLASS_RESOURCE => array()); foreach ($modules as $module) { - if (isset($module->types)) { - // This module has a subtype - // NOTE: this is legacy stuff, module subtypes are very strongly discouraged!! - $subtypes = array(); - foreach ($module->types as $subtype) { - $link = $subtype->link->out(true, $urlparams); - $subtypes[$link] = $subtype->title; - } - - // Sort module subtypes into the list - $activityclass = MOD_CLASS_ACTIVITY; - if ($module->archetype == MOD_CLASS_RESOURCE) { - $activityclass = MOD_CLASS_RESOURCE; - } - if (!empty($module->title)) { - // This grouping has a name - $activities[$activityclass][] = array($module->title => $subtypes); - } else { - // This grouping does not have a name - $activities[$activityclass] = array_merge($activities[$activityclass], $subtypes); - } - } else { - // This module has no subtypes - $activityclass = MOD_CLASS_ACTIVITY; - if ($module->archetype == MOD_ARCHETYPE_RESOURCE) { - $activityclass = MOD_CLASS_RESOURCE; - } else if ($module->archetype === MOD_ARCHETYPE_SYSTEM) { - // System modules cannot be added by user, do not add to dropdown - continue; - } - $link = $module->link->out(true, $urlparams); - $activities[$activityclass][$link] = $module->title; + $activityclass = MOD_CLASS_ACTIVITY; + if ($module->archetype == MOD_ARCHETYPE_RESOURCE) { + $activityclass = MOD_CLASS_RESOURCE; + } else if ($module->archetype === MOD_ARCHETYPE_SYSTEM) { + // System modules cannot be added by user, do not add to dropdown. + continue; } + $link = $module->link->out(true, $urlparams); + $activities[$activityclass][$link] = $module->title; } $straddactivity = get_string('addactivity'); diff --git a/lang/en/moodle.php b/lang/en/moodle.php index 237e9205384..a5407741470 100644 --- a/lang/en/moodle.php +++ b/lang/en/moodle.php @@ -39,6 +39,7 @@ $string['activityreport'] = 'Activity report'; $string['activityreports'] = 'Activity reports'; $string['activityselect'] = 'Select this activity to be moved elsewhere'; $string['activitysince'] = 'Activity since {$a}'; +$string['activitytypetitle'] = '{$a->activity} - {$a->type}'; $string['activityweighted'] = 'Activity per user'; $string['add'] = 'Add'; $string['addactivity'] = 'Add an activity...'; diff --git a/lib/moodlelib.php b/lib/moodlelib.php index 44dc966c352..ff73eb368d4 100644 --- a/lib/moodlelib.php +++ b/lib/moodlelib.php @@ -448,7 +448,11 @@ define('MOD_ARCHETYPE_ASSIGNMENT', 2); /** System (not user-addable) module archetype */ define('MOD_ARCHETYPE_SYSTEM', 3); -/** Return this from modname_get_types callback to use default display in activity chooser */ +/** + * Return this from modname_get_types callback to use default display in activity chooser. + * Deprecated, will be removed in 3.5, TODO MDL-53697. + * @deprecated since Moodle 3.1 + */ define('MOD_SUBTYPE_NO_CHILDREN', 'modsubtypenochildren'); /** diff --git a/mod/upgrade.txt b/mod/upgrade.txt index c8b4998da30..ad0c75de3b9 100644 --- a/mod/upgrade.txt +++ b/mod/upgrade.txt @@ -5,6 +5,8 @@ information provided here is intended especially for developers. * Old /mod/MODULENAME/pix/icon.gif and enrol/paypal/pix/icon.gif GIF icons have been removed. Please use pix_icon renderable instead. +* Callback get_types() is deprecated, instead activity modules can define callback get_shortcuts(). + See source code for get_module_metadata(). === 3.0 ===