From 8982cc61b33976e88cc30032d6821541e3a0b1da Mon Sep 17 00:00:00 2001 From: Jake Dallimore Date: Mon, 16 Sep 2024 15:44:37 +0800 Subject: [PATCH] MDL-80746 core_course: fix user_selector rendering This change: - Moved the user selector button content out into its own named_templatable renderable + updates calling code --- .../output/actionbar/user_selector.php | 65 ++++++----------- .../output/actionbar/user_selector_button.php | 73 +++++++++++++++++++ 2 files changed, 96 insertions(+), 42 deletions(-) create mode 100644 course/classes/output/actionbar/user_selector_button.php diff --git a/course/classes/output/actionbar/user_selector.php b/course/classes/output/actionbar/user_selector.php index 6afba7196c2..9eed7dd7da8 100644 --- a/course/classes/output/actionbar/user_selector.php +++ b/course/classes/output/actionbar/user_selector.php @@ -40,57 +40,38 @@ class user_selector extends comboboxsearch { * @param int|null $instanceid The instance ID. */ public function __construct( - stdClass $course, - moodle_url $resetlink, - ?int $userid = null, - ?int $groupid = null, - string $usersearch = '', - ?int $instanceid = null + private stdClass $course, + private moodle_url $resetlink, + private ?int $userid = null, + private ?int $groupid = null, + private string $usersearch = '', + private ?int $instanceid = null ) { - - $userselectorontent = $this->user_selector_output($course, $resetlink, $userid, $groupid, $usersearch, $instanceid); - parent::__construct(true, $userselectorontent, null, 'user-search d-flex', + // The second argument (buttoncontent) needs to be rendered here, since the comboboxsearch + // template expects HTML in its respective context properties. Ideally, children of comboboxsearch would leverage Mustache's + // blocks pragma, meaning a child template could extend the comboboxsearch, allowing rendering of the child component, + // instead of needing to inject the child's content HTML as part of rendering the comboboxsearch parent, as is the case + // here. Achieving this, however, requires a refactor of comboboxsearch. For now, this must be pre-rendered and injected. + parent::__construct(true, $this->user_selector_output(), null, 'user-search d-flex', null, 'usersearchdropdown overflow-auto', null, false); } /** * Method that generates the output for the user selector. * - * @param stdClass $course The course object. - * @param moodle_url|null $resetlink The reset link. - * @param int|null $userid The user ID. - * @param int|null $groupid The group ID. - * @param string $usersearch The user search query. - * @param int|null $instanceid The instance ID. * @return string The HTML output. */ - private function user_selector_output( - stdClass $course, - ?moodle_url $resetlink = null, - ?int $userid = null, - ?int $groupid = null, - string $usersearch = '', - ?int $instanceid = null - ): string { - global $OUTPUT; + private function user_selector_output(): string { + global $PAGE; - // If the user ID is set, it indicates that a user has been selected. In this case, override the user search - // string with the full name of the selected user. - if ($userid) { - $usersearch = fullname(\core_user::get_user($userid)); - } - - return $OUTPUT->render_from_template('core_user/comboboxsearch/user_selector', [ - 'currentvalue' => $usersearch, - 'courseid' => $course->id, - 'instance' => $instanceid ?? rand(), - 'resetlink' => $resetlink->out(false), - 'group' => $groupid ?? 0, - 'name' => 'usersearch', - 'value' => json_encode([ - 'userid' => $userid, - 'search' => $usersearch, - ]), - ]); + $userselectordropdown = new user_selector_button( + $this->course, + $this->resetlink, + $this->userid, + $this->groupid, + $this->usersearch, + $this->instanceid + ); + return $PAGE->get_renderer('core', 'course')->render($userselectordropdown); } } diff --git a/course/classes/output/actionbar/user_selector_button.php b/course/classes/output/actionbar/user_selector_button.php new file mode 100644 index 00000000000..1b522475eb0 --- /dev/null +++ b/course/classes/output/actionbar/user_selector_button.php @@ -0,0 +1,73 @@ +. + +namespace core_course\output\actionbar; + +use core\output\named_templatable; +use core\output\renderable; +use core\output\renderer_base; +use core\url; +use stdClass; + +/** + * Renderable class for the user_selector_button. + * + * This is the button content for the user_selector renderable, which itself is an extension of the comboboxsearch component. + * {@see initials_selector}. + * + * @package core_course + * @copyright 2024 Jake Dallimore + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class user_selector_button implements renderable, named_templatable { + + /** + * The class constructor. + */ + public function __construct( + private stdClass $course, + private url $resetlink, + private ?int $userid = null, + private ?int $groupid = null, + private string $usersearch = '', + private ?int $instanceid = null + ) { + // If the user ID is set, it indicates that a user has been selected. In this case, override the user search + // string with the full name of the selected user. + if ($this->userid) { + $this->usersearch = fullname(\core_user::get_user($this->userid)); + } + } + + public function export_for_template(renderer_base $output) { + return [ + 'currentvalue' => $this->usersearch, + 'courseid' => $this->course->id, + 'instance' => $this->instanceid ?? rand(), + 'resetlink' => $this->resetlink->out(false), + 'group' => $this->groupid ?? 0, + 'name' => 'usersearch', + 'value' => json_encode([ + 'userid' => $this->userid, + 'search' => $this->usersearch, + ]), + ]; + } + + public function get_template_name(renderer_base $renderer): string { + return 'core_user/comboboxsearch/user_selector'; + } +}