PageRenderTime 74ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/theme/boost/classes/output/core_renderer.php

https://bitbucket.org/moodle/moodle
PHP | 282 lines | 186 code | 29 blank | 67 comment | 41 complexity | 4ff4807d67a399238c1a7f44f10dff40 MD5 | raw file
Possible License(s): Apache-2.0, LGPL-2.1, BSD-3-Clause, MIT, GPL-3.0
  1. <?php
  2. // This file is part of Moodle - http://moodle.org/
  3. //
  4. // Moodle is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // Moodle is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License
  15. // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
  16. namespace theme_boost\output;
  17. use moodle_url;
  18. use html_writer;
  19. use get_string;
  20. defined('MOODLE_INTERNAL') || die;
  21. /**
  22. * Renderers to align Moodle's HTML with that expected by Bootstrap
  23. *
  24. * @package theme_boost
  25. * @copyright 2012 Bas Brands, www.basbrands.nl
  26. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  27. */
  28. class core_renderer extends \core_renderer {
  29. public function edit_button(moodle_url $url) {
  30. if ($this->page->theme->haseditswitch) {
  31. return;
  32. }
  33. $url->param('sesskey', sesskey());
  34. if ($this->page->user_is_editing()) {
  35. $url->param('edit', 'off');
  36. $editstring = get_string('turneditingoff');
  37. } else {
  38. $url->param('edit', 'on');
  39. $editstring = get_string('turneditingon');
  40. }
  41. $button = new \single_button($url, $editstring, 'post', ['class' => 'btn btn-primary']);
  42. return $this->render_single_button($button);
  43. }
  44. /**
  45. * Renders the "breadcrumb" for all pages in boost.
  46. *
  47. * @return string the HTML for the navbar.
  48. */
  49. public function navbar(): string {
  50. $newnav = new \theme_boost\boostnavbar($this->page->navbar);
  51. return $this->render_from_template('core/navbar', $newnav);
  52. }
  53. /**
  54. * Renders the context header for the page.
  55. *
  56. * @param array $headerinfo Heading information.
  57. * @param int $headinglevel What 'h' level to make the heading.
  58. * @return string A rendered context header.
  59. */
  60. public function context_header($headerinfo = null, $headinglevel = 1): string {
  61. global $DB, $USER, $CFG, $SITE;
  62. require_once($CFG->dirroot . '/user/lib.php');
  63. $context = $this->page->context;
  64. $heading = null;
  65. $imagedata = null;
  66. $subheader = null;
  67. $userbuttons = null;
  68. // Make sure to use the heading if it has been set.
  69. if (isset($headerinfo['heading'])) {
  70. $heading = $headerinfo['heading'];
  71. } else {
  72. $heading = $this->page->heading;
  73. }
  74. // The user context currently has images and buttons. Other contexts may follow.
  75. if (isset($headerinfo['user']) || $context->contextlevel == CONTEXT_USER) {
  76. if (isset($headerinfo['user'])) {
  77. $user = $headerinfo['user'];
  78. } else {
  79. // Look up the user information if it is not supplied.
  80. $user = $DB->get_record('user', array('id' => $context->instanceid));
  81. }
  82. // If the user context is set, then use that for capability checks.
  83. if (isset($headerinfo['usercontext'])) {
  84. $context = $headerinfo['usercontext'];
  85. }
  86. // Only provide user information if the user is the current user, or a user which the current user can view.
  87. // When checking user_can_view_profile(), either:
  88. // If the page context is course, check the course context (from the page object) or;
  89. // If page context is NOT course, then check across all courses.
  90. $course = ($this->page->context->contextlevel == CONTEXT_COURSE) ? $this->page->course : null;
  91. if (user_can_view_profile($user, $course)) {
  92. // Use the user's full name if the heading isn't set.
  93. if (empty($heading)) {
  94. $heading = fullname($user);
  95. }
  96. $imagedata = $this->user_picture($user, array('size' => 100));
  97. // Check to see if we should be displaying a message button.
  98. if (!empty($CFG->messaging) && has_capability('moodle/site:sendmessage', $context)) {
  99. $userbuttons = array(
  100. 'messages' => array(
  101. 'buttontype' => 'message',
  102. 'title' => get_string('message', 'message'),
  103. 'url' => new moodle_url('/message/index.php', array('id' => $user->id)),
  104. 'image' => 'message',
  105. 'linkattributes' => \core_message\helper::messageuser_link_params($user->id),
  106. 'page' => $this->page
  107. )
  108. );
  109. if ($USER->id != $user->id) {
  110. $iscontact = \core_message\api::is_contact($USER->id, $user->id);
  111. $contacttitle = $iscontact ? 'removefromyourcontacts' : 'addtoyourcontacts';
  112. $contacturlaction = $iscontact ? 'removecontact' : 'addcontact';
  113. $contactimage = $iscontact ? 'removecontact' : 'addcontact';
  114. $userbuttons['togglecontact'] = array(
  115. 'buttontype' => 'togglecontact',
  116. 'title' => get_string($contacttitle, 'message'),
  117. 'url' => new moodle_url('/message/index.php', array(
  118. 'user1' => $USER->id,
  119. 'user2' => $user->id,
  120. $contacturlaction => $user->id,
  121. 'sesskey' => sesskey())
  122. ),
  123. 'image' => $contactimage,
  124. 'linkattributes' => \core_message\helper::togglecontact_link_params($user, $iscontact),
  125. 'page' => $this->page
  126. );
  127. }
  128. $this->page->requires->string_for_js('changesmadereallygoaway', 'moodle');
  129. }
  130. } else {
  131. $heading = null;
  132. }
  133. }
  134. $prefix = null;
  135. if ($context->contextlevel == CONTEXT_MODULE) {
  136. $heading = $this->page->cm->get_formatted_name();
  137. $imagedata = $this->pix_icon('icon', '', $this->page->activityname);
  138. $prefix = get_string('modulename', $this->page->activityname);
  139. }
  140. if ($this->should_display_main_logo($headinglevel)) {
  141. $sitename = format_string($SITE->fullname, true, ['context' => \context_course::instance(SITEID)]);
  142. // Logo.
  143. $html = html_writer::div(
  144. html_writer::empty_tag('img', [
  145. 'src' => $this->get_logo_url(null, 150),
  146. 'alt' => get_string('logoof', '', $sitename),
  147. 'class' => 'img-fluid'
  148. ]),
  149. 'logo'
  150. );
  151. // Heading.
  152. if (!isset($heading)) {
  153. $html .= $this->heading($this->page->heading, $headinglevel, 'sr-only');
  154. } else {
  155. $html .= $this->heading($heading, $headinglevel, 'sr-only');
  156. }
  157. return $html;
  158. }
  159. $contextheader = new \context_header($heading, $headinglevel, $imagedata, $userbuttons, $prefix);
  160. return $this->render_context_header($contextheader);
  161. }
  162. /**
  163. * Renders the header bar.
  164. *
  165. * @param context_header $contextheader Header bar object.
  166. * @return string HTML for the header bar.
  167. */
  168. protected function render_context_header(\context_header $contextheader) {
  169. // Generate the heading first and before everything else as we might have to do an early return.
  170. if (!isset($contextheader->heading)) {
  171. $heading = $this->heading($this->page->heading, $contextheader->headinglevel, 'h2');
  172. } else {
  173. $heading = $this->heading($contextheader->heading, $contextheader->headinglevel, 'h2');
  174. }
  175. $showheader = empty($this->page->layout_options['nocontextheader']);
  176. if (!$showheader) {
  177. // Return the heading wrapped in an sr-only element so it is only visible to screen-readers.
  178. return html_writer::div($heading, 'sr-only');
  179. }
  180. // All the html stuff goes here.
  181. $html = html_writer::start_div('page-context-header');
  182. // Image data.
  183. if (isset($contextheader->imagedata)) {
  184. // Header specific image.
  185. $html .= html_writer::div($contextheader->imagedata, 'page-header-image icon-size-6');
  186. }
  187. // Headings.
  188. if (isset($contextheader->prefix)) {
  189. $prefix = html_writer::div($contextheader->prefix, 'text-muted text-uppercase');
  190. $heading = $prefix . $heading;
  191. }
  192. $html .= html_writer::tag('div', $heading, array('class' => 'page-header-headings'));
  193. // Buttons.
  194. if (isset($contextheader->additionalbuttons)) {
  195. $html .= html_writer::start_div('btn-group header-button-group');
  196. foreach ($contextheader->additionalbuttons as $button) {
  197. if (!isset($button->page)) {
  198. // Include js for messaging.
  199. if ($button['buttontype'] === 'togglecontact') {
  200. \core_message\helper::togglecontact_requirejs();
  201. }
  202. if ($button['buttontype'] === 'message') {
  203. \core_message\helper::messageuser_requirejs();
  204. }
  205. $image = $this->pix_icon($button['formattedimage'], $button['title'], 'moodle', array(
  206. 'class' => 'iconsmall',
  207. 'role' => 'presentation'
  208. ));
  209. $image .= html_writer::span($button['title'], 'header-button-title');
  210. } else {
  211. $image = html_writer::empty_tag('img', array(
  212. 'src' => $button['formattedimage'],
  213. 'role' => 'presentation'
  214. ));
  215. }
  216. $html .= html_writer::link($button['url'], html_writer::tag('span', $image), $button['linkattributes']);
  217. }
  218. $html .= html_writer::end_div();
  219. }
  220. $html .= html_writer::end_div();
  221. return $html;
  222. }
  223. /**
  224. * See if this is the first view of the current cm in the session if it has fake blocks.
  225. *
  226. * (We track up to 100 cms so as not to overflow the session.)
  227. * This is done for drawer regions containing fake blocks so we can show blocks automatically.
  228. *
  229. * @return boolean true if the page has fakeblocks and this is the first visit.
  230. */
  231. public function firstview_fakeblocks(): bool {
  232. global $SESSION;
  233. $firstview = false;
  234. if ($this->page->cm) {
  235. if (!$this->page->blocks->region_has_fakeblocks('side-pre')) {
  236. return false;
  237. }
  238. if (!property_exists($SESSION, 'firstview_fakeblocks')) {
  239. $SESSION->firstview_fakeblocks = [];
  240. }
  241. if (array_key_exists($this->page->cm->id, $SESSION->firstview_fakeblocks)) {
  242. $firstview = false;
  243. } else {
  244. $SESSION->firstview_fakeblocks[$this->page->cm->id] = true;
  245. $firstview = true;
  246. if (count($SESSION->firstview_fakeblocks) > 100) {
  247. array_shift($SESSION->firstview_fakeblocks);
  248. }
  249. }
  250. }
  251. return $firstview;
  252. }
  253. }