Skip to content

Commit

Permalink
MDL-83527 core_courseformat: refactor course editor action menus
Browse files Browse the repository at this point in the history
As part of the course format cleanup epic, all course editor action menu
output classes needs to be refactored to be more mantainable and
reusable. Also, it added notes for the final deprecation of many lines
of code in Moodle 6.0.
  • Loading branch information
ferranrecio committed Nov 26, 2024
1 parent 694edcf commit 9f28b89
Show file tree
Hide file tree
Showing 6 changed files with 1,127 additions and 92 deletions.
125 changes: 101 additions & 24 deletions course/format/classes/output/local/content/basecontrolmenu.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,16 @@

namespace core_courseformat\output\local\content;

use action_menu;
use action_menu_link_secondary;
use core\context\course as context_course;
use core\output\action_menu;
use core\output\action_menu\link_secondary;
use core\output\named_templatable;
use core\output\pix_icon;
use core\output\renderable;
use core\output\renderer_base;
use core_courseformat\base as course_format;
use core_courseformat\output\local\courseformat_named_templatable;
use moodle_url;
use pix_icon;
use renderable;
use core\url;
use section_info;
use cm_info;
use stdClass;
Expand All @@ -48,12 +50,21 @@ abstract class basecontrolmenu implements named_templatable, renderable {
/** @var cm_info the course module class */
protected $mod;

/** @var stdClass the course instance */
protected stdClass $course;

/** @var context_course the course context */
protected $coursecontext;

/** @var string the menu ID */
protected $menuid;

/** @var action_menu the action menu */
protected $menu;

/** @var url The base URL for the course or the section */
protected url $baseurl;

/**
* Constructor.
*
Expand All @@ -67,15 +78,18 @@ public function __construct(course_format $format, section_info $section, ?cm_in
$this->section = $section;
$this->mod = $mod;
$this->menuid = $menuid;
$this->course = $format->get_course();
$this->coursecontext = $format->get_context();
$this->baseurl = $format->get_view_url($format->get_sectionnum(), ['navigation' => true]);
}

/**
* Export this data so it can be used as the context for a mustache template.
*
* @param \renderer_base $output typically, the renderer that's calling this function
* @param renderer_base $output typically, the renderer that's calling this function
* @return null|array data context for a mustache template
*/
public function export_for_template(\renderer_base $output): ?stdClass {
public function export_for_template(renderer_base $output): ?stdClass {
$menu = $this->get_action_menu($output);
if (empty($menu)) {
return new stdClass();
Expand All @@ -93,10 +107,10 @@ public function export_for_template(\renderer_base $output): ?stdClass {
/**
* Generate the action menu element.
*
* @param \renderer_base $output typically, the renderer that's calling this function
* @param renderer_base $output typically, the renderer that's calling this function
* @return action_menu|null the action menu or null if no action menu is available
*/
public function get_action_menu(\renderer_base $output): ?action_menu {
public function get_action_menu(renderer_base $output): ?action_menu {

if (!empty($this->menu)) {
return $this->menu;
Expand All @@ -111,10 +125,10 @@ public function get_action_menu(\renderer_base $output): ?action_menu {
*
* This method is public in case some block needs to modify the menu before output it.
*
* @param \renderer_base $output typically, the renderer that's calling this function
* @param renderer_base $output typically, the renderer that's calling this function
* @return action_menu|null the action menu
*/
public function get_default_action_menu(\renderer_base $output): ?action_menu {
public function get_default_action_menu(renderer_base $output): ?action_menu {
return null;
}

Expand All @@ -133,23 +147,57 @@ protected function format_controls(array $controls): ?action_menu {
$menu->set_kebab_trigger(get_string('edit'));
$menu->attributes['class'] .= ' section-actions';
$menu->attributes['data-sectionid'] = $this->section->id;
foreach ($controls as $value) {
$url = empty($value['url']) ? '' : $value['url'];
$icon = empty($value['icon']) ? '' : $value['icon'];
$name = empty($value['name']) ? '' : $value['name'];
$attr = empty($value['attr']) ? [] : $value['attr'];
$class = empty($value['pixattr']['class']) ? '' : $value['pixattr']['class'];
$al = new action_menu_link_secondary(
new moodle_url($url),
new pix_icon($icon, '', null, ['class' => "smallicon " . $class]),
$name,
$attr
);
$menu->add($al);
foreach ($controls as $item) {
// Actions not available for the user can be null.
if ($item === null) {
continue;
}

// TODO remove this if as part of MDL-83530.
if (is_array($item)) {
// Some third party formats from 4.5 and older can use array to define the action menu items.
$item = $this->normalize_action_menu_link($item);
}

$menu->add($item);
}
return $menu;
}

/**
* Nromalize the action menu item, or return null if it is not possible.
*
* Traditionally, this class uses array to define the action menu items,
* for backward compatibility, this method will normalize the array into
* te correct action_menu_link object.
*
* @todo Remove this method in Moodle 6.0 (MDL-83530).
* @param array|null $itemdata the item data
* @return void
*/
private function normalize_action_menu_link(
array|null $itemdata
): ?link_secondary {
debugging(
"Using arrays as action menu items is deprecated, use a compatible menu item instead.",
DEBUG_DEVELOPER
);
if (empty($itemdata)) {
return null;
}
$url = empty($itemdata['url']) ? '' : $itemdata['url'];
$icon = empty($itemdata['icon']) ? '' : $itemdata['icon'];
$name = empty($itemdata['name']) ? '' : $itemdata['name'];
$attr = empty($itemdata['attr']) ? [] : $itemdata['attr'];
$class = empty($itemdata['pixattr']['class']) ? '' : $itemdata['pixattr']['class'];
return new link_secondary(
url: new url($url),
icon: new pix_icon($icon, '', null, ['class' => "smallicon " . $class]),
text: $name,
attributes: $attr,
);
}

/**
* Generate the edit control items of a section.
*
Expand All @@ -160,4 +208,33 @@ protected function format_controls(array $controls): ?action_menu {
public function section_control_items() {
return [];
}

/**
* Adds a new control item after a given control item.
*
* If the control item is not found, the new control item is added at the beginning.
*
* @param array $controls array of edit control items
* @param string $aftername name of the control item after which the new control item will be added
* @param string $newkey key of the new control item
* @param mixed $newcontrol new control item to be added (anything compatible with an action menu or null)
*/
protected function add_control_after(array $controls, string $aftername, string $newkey, mixed $newcontrol): array {
if (!array_key_exists($aftername, $controls)) {
return array_merge([$newkey => $newcontrol], $controls);
}
$newcontrols = [];
$found = false;
foreach ($controls as $keyname => $control) {
$newcontrols[$keyname] = $control;
if ($keyname === $aftername) {
$newcontrols[$newkey] = $newcontrol;
$found = true;
}
}
if (!$found) {
$newcontrols[$newkey] = $newcontrol;
}
return $newcontrols;
}
}
Loading

0 comments on commit 9f28b89

Please sign in to comment.