Skip to content

Commit

Permalink
MDL-83527 core_courseformat: refactor section action menu
Browse files Browse the repository at this point in the history
  • Loading branch information
ferranrecio committed Oct 24, 2024
1 parent ecfcf00 commit a32a399
Show file tree
Hide file tree
Showing 4 changed files with 480 additions and 27 deletions.
294 changes: 279 additions & 15 deletions course/format/classes/output/local/content/basecontrolmenu.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,15 @@

namespace core_courseformat\output\local\content;

use action_menu;
use action_menu_link_secondary;
use core\output\action_menu;
use core\output\action_menu\link as action_menu_link;
use core\output\action_menu\link_secondary as action_menu_link_secondary;
use core\output\named_templatable;
use core\output\pix_icon;
use core_courseformat\base as course_format;
use core_courseformat\output\local\courseformat_named_templatable;
use context_course;
use moodle_url;
use pix_icon;
use renderable;
use section_info;
use cm_info;
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 moodle_url The base URL for the course or the section */
protected moodle_url $baseurl;

/**
* Constructor.
*
Expand All @@ -67,6 +78,9 @@ 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]);
}

/**
Expand Down Expand Up @@ -134,22 +148,50 @@ protected function format_controls(array $controls): ?action_menu {
$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);
// Some third party formats can use array to define the action menu items.
$item = $this->normalize_action_menu_link($value);
// Actions not available for the user can be null.
if ($item === null) {
continue;
}
$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.
*
* @param array|action_menu_link|null $itemdata the item data
* @return void
*/
protected function normalize_action_menu_link(
array|action_menu_link|null $itemdata
): ?action_menu_link_secondary {
if (empty($itemdata)) {
return null;
}
if ($itemdata instanceof action_menu_link) {
return $itemdata;
}

$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 action_menu_link_secondary(
new moodle_url($url),
new pix_icon($icon, '', null, ['class' => "smallicon " . $class]),
$name,
$attr
);
}

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

// Section items.

/**
* Retrieves the view item for the section control menu.
*
* @return action_menu_link|null The menu item if applicable, otherwise null.
*/
protected function get_section_view_item(): ?action_menu_link {
// Only show the view link if we are not already in the section view page.
if ($this->format->get_sectionid() == $this->section->id) {
return null;
}
return $this->normalize_action_menu_link([
'url' => new moodle_url('/course/section.php', ['id' => $this->section->id]),
'icon' => 'i/viewsection',
'name' => get_string('view'),
'pixattr' => ['class' => ''],
'attr' => ['class' => 'icon view'],
]);
}

/**
* Retrieves the edit item for the section control menu.
*
* @return action_menu_link|null The menu item if applicable, otherwise null.
*/
protected function get_section_edit_item(): ?action_menu_link {
if (!has_capability('moodle/course:update', $this->coursecontext)) {
return null;
}
$params = ['id' => $this->section->id];
$params['sr'] = $this->section->section;
return $this->normalize_action_menu_link([
'url' => new moodle_url('/course/editsection.php', $params),
'icon' => 'i/settings',
'name' => get_string('editsection'),
'pixattr' => ['class' => ''],
'attr' => ['class' => 'icon edit'],
]);
}

/**
* Retrieves the duplicate item for the section control menu.
*
* @return action_menu_link|null The menu item if applicable, otherwise null.
*/
protected function get_section_duplicate_item(): ?action_menu_link {
if (
$this->section->sectionnum == 0
|| !has_capability('moodle/course:update', $this->coursecontext)
) {
return null;
}
$url = clone($this->baseurl);
$url->param('sectionid', $this->section->id);
$url->param('duplicatesection', 1);
$url->param('sesskey', sesskey());
return $this->normalize_action_menu_link([
'url' => $url,
'icon' => 't/copy',
'name' => get_string('duplicate'),
'pixattr' => ['class' => ''],
'attr' => ['class' => 'icon duplicate'],
]);
}

/**
* Retrieves the get_section_visibility_menu_item item for the section control menu.
*
* @return action_menu_link|null The menu item if applicable, otherwise null.
*/
protected function get_section_visibility_item(): ?action_menu_link {
if (
$this->section->sectionnum == 0
|| !has_capability('moodle/course:sectionvisibility', $this->coursecontext)
) {
return null;
}
$sectionreturn = $this->format->get_sectionnum();

$url = clone($this->baseurl);

$strhide = get_string('hide');
$strshow = get_string('show');

if ($this->section->visible) {
$url->param('hide', $this->section->sectionnum);
$item = [
'url' => $url,
'icon' => 'i/show',
'name' => $strhide,
'pixattr' => ['class' => ''],
'attr' => [
'class' => 'icon editing_showhide',
'data-sectionreturn' => $sectionreturn,
'data-action' => 'sectionHide',
'data-id' => $this->section->id,
'data-icon' => 'i/show',
'data-swapname' => $strshow,
'data-swapicon' => 'i/hide',
],
];
} else {
$url->param('show', $this->section->sectionnum);
$item = [
'url' => $url,
'icon' => 'i/hide',
'name' => $strshow,
'pixattr' => ['class' => ''],
'attr' => [
'class' => 'icon editing_showhide',
'data-sectionreturn' => $sectionreturn,
'data-action' => 'sectionShow',
'data-id' => $this->section->id,
'data-icon' => 'i/hide',
'data-swapname' => $strhide,
'data-swapicon' => 'i/show',
],
];
}
return $this->normalize_action_menu_link($item);
}

/**
* Retrieves the move item for the section control menu.
*
* @return action_menu_link|null The menu item if applicable, otherwise null.
*/
protected function get_section_movesection_item(): ?action_menu_link {
if (
$this->section->sectionnum == 0
|| $this->format->get_sectionid()
|| !has_capability('moodle/course:movesections', $this->coursecontext)
) {
return null;
}

$url = clone ($this->baseurl);
$url->param('movesection', $this->section->sectionnum);
$url->param('section', $this->section->sectionnum);
return $this->normalize_action_menu_link([
'url' => $url,
'icon' => 'i/dragdrop',
'name' => get_string('move'),
'pixattr' => ['class' => ''],
'attr' => [
// This tool requires ajax and will appear only when the frontend state is ready.
'class' => 'icon move waitstate',
'data-action' => 'moveSection',
'data-id' => $this->section->id,
],
]);
}

/**
* Retrieves the permalink item for the section control menu.
*
* @return action_menu_link|null The menu item if applicable, otherwise null.
*/
protected function get_section_permalink_item(): ?action_menu_link {
if (!has_any_capability(
[
'moodle/course:movesections',
'moodle/course:update',
'moodle/course:sectionvisibility',
],
$this->coursecontext
)
) {
return null;
}

$url = new moodle_url(
'/course/section.php',
['id' => $this->section->id]
);
return $this->normalize_action_menu_link([
'url' => $url,
'icon' => 'i/link',
'name' => get_string('sectionlink', 'course'),
'pixattr' => ['class' => ''],
'attr' => [
'class' => 'icon',
'data-action' => 'permalink',
],
]);
}

/**
* Retrieves the delete item for the section control menu.
*
* @return action_menu_link|null The menu item if applicable, otherwise null.
*/
protected function get_section_delete_item(): ?action_menu_link {
if (!course_can_delete_section($this->format->get_course(), $this->section)) {
return null;
}

$params = [
'id' => $this->section->id,
'delete' => 1,
'sesskey' => sesskey(),
];
$params['sr'] ??= $this->format->get_sectionnum();

$url = new moodle_url(
'/course/editsection.php',
$params,
);
return $this->normalize_action_menu_link([
'url' => $url,
'icon' => 'i/delete',
'name' => get_string('delete'),
'pixattr' => ['class' => ''],
'attr' => [
'class' => 'icon editing_delete text-danger',
'data-action' => 'deleteSection',
'data-id' => $this->section->id,
],
]);
}
}
Loading

0 comments on commit a32a399

Please sign in to comment.