PageRenderTime 70ms CodeModel.GetById 30ms RepoModel.GetById 1ms app.codeStats 0ms

/mod/lesson/locallib.php

https://bitbucket.org/synergylearning/campusconnect
PHP | 2845 lines | 1552 code | 261 blank | 1032 comment | 382 complexity | 09ae0802d37cc3bcf92badef8eea6279 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, LGPL-3.0, GPL-3.0, LGPL-2.1, Apache-2.0, BSD-3-Clause, AGPL-3.0

Large files files are truncated, but you can click here to view the full file

  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. /**
  17. * Local library file for Lesson. These are non-standard functions that are used
  18. * only by Lesson.
  19. *
  20. * @package mod
  21. * @subpackage lesson
  22. * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
  23. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or late
  24. **/
  25. /** Make sure this isn't being directly accessed */
  26. defined('MOODLE_INTERNAL') || die();
  27. /** Include the files that are required by this module */
  28. require_once($CFG->dirroot.'/course/moodleform_mod.php');
  29. require_once($CFG->dirroot . '/mod/lesson/lib.php');
  30. require_once($CFG->libdir . '/filelib.php');
  31. /** This page */
  32. define('LESSON_THISPAGE', 0);
  33. /** Next page -> any page not seen before */
  34. define("LESSON_UNSEENPAGE", 1);
  35. /** Next page -> any page not answered correctly */
  36. define("LESSON_UNANSWEREDPAGE", 2);
  37. /** Jump to Next Page */
  38. define("LESSON_NEXTPAGE", -1);
  39. /** End of Lesson */
  40. define("LESSON_EOL", -9);
  41. /** Jump to an unseen page within a branch and end of branch or end of lesson */
  42. define("LESSON_UNSEENBRANCHPAGE", -50);
  43. /** Jump to Previous Page */
  44. define("LESSON_PREVIOUSPAGE", -40);
  45. /** Jump to a random page within a branch and end of branch or end of lesson */
  46. define("LESSON_RANDOMPAGE", -60);
  47. /** Jump to a random Branch */
  48. define("LESSON_RANDOMBRANCH", -70);
  49. /** Cluster Jump */
  50. define("LESSON_CLUSTERJUMP", -80);
  51. /** Undefined */
  52. define("LESSON_UNDEFINED", -99);
  53. /** LESSON_MAX_EVENT_LENGTH = 432000 ; 5 days maximum */
  54. define("LESSON_MAX_EVENT_LENGTH", "432000");
  55. //////////////////////////////////////////////////////////////////////////////////////
  56. /// Any other lesson functions go here. Each of them must have a name that
  57. /// starts with lesson_
  58. /**
  59. * Checks to see if a LESSON_CLUSTERJUMP or
  60. * a LESSON_UNSEENBRANCHPAGE is used in a lesson.
  61. *
  62. * This function is only executed when a teacher is
  63. * checking the navigation for a lesson.
  64. *
  65. * @param stdClass $lesson Id of the lesson that is to be checked.
  66. * @return boolean True or false.
  67. **/
  68. function lesson_display_teacher_warning($lesson) {
  69. global $DB;
  70. // get all of the lesson answers
  71. $params = array ("lessonid" => $lesson->id);
  72. if (!$lessonanswers = $DB->get_records_select("lesson_answers", "lessonid = :lessonid", $params)) {
  73. // no answers, then not using cluster or unseen
  74. return false;
  75. }
  76. // just check for the first one that fulfills the requirements
  77. foreach ($lessonanswers as $lessonanswer) {
  78. if ($lessonanswer->jumpto == LESSON_CLUSTERJUMP || $lessonanswer->jumpto == LESSON_UNSEENBRANCHPAGE) {
  79. return true;
  80. }
  81. }
  82. // if no answers use either of the two jumps
  83. return false;
  84. }
  85. /**
  86. * Interprets the LESSON_UNSEENBRANCHPAGE jump.
  87. *
  88. * will return the pageid of a random unseen page that is within a branch
  89. *
  90. * @param lesson $lesson
  91. * @param int $userid Id of the user.
  92. * @param int $pageid Id of the page from which we are jumping.
  93. * @return int Id of the next page.
  94. **/
  95. function lesson_unseen_question_jump($lesson, $user, $pageid) {
  96. global $DB;
  97. // get the number of retakes
  98. if (!$retakes = $DB->count_records("lesson_grades", array("lessonid"=>$lesson->id, "userid"=>$user))) {
  99. $retakes = 0;
  100. }
  101. // get all the lesson_attempts aka what the user has seen
  102. if ($viewedpages = $DB->get_records("lesson_attempts", array("lessonid"=>$lesson->id, "userid"=>$user, "retry"=>$retakes), "timeseen DESC")) {
  103. foreach($viewedpages as $viewed) {
  104. $seenpages[] = $viewed->pageid;
  105. }
  106. } else {
  107. $seenpages = array();
  108. }
  109. // get the lesson pages
  110. $lessonpages = $lesson->load_all_pages();
  111. if ($pageid == LESSON_UNSEENBRANCHPAGE) { // this only happens when a student leaves in the middle of an unseen question within a branch series
  112. $pageid = $seenpages[0]; // just change the pageid to the last page viewed inside the branch table
  113. }
  114. // go up the pages till branch table
  115. while ($pageid != 0) { // this condition should never be satisfied... only happens if there are no branch tables above this page
  116. if ($lessonpages[$pageid]->qtype == LESSON_PAGE_BRANCHTABLE) {
  117. break;
  118. }
  119. $pageid = $lessonpages[$pageid]->prevpageid;
  120. }
  121. $pagesinbranch = $lesson->get_sub_pages_of($pageid, array(LESSON_PAGE_BRANCHTABLE, LESSON_PAGE_ENDOFBRANCH));
  122. // this foreach loop stores all the pages that are within the branch table but are not in the $seenpages array
  123. $unseen = array();
  124. foreach($pagesinbranch as $page) {
  125. if (!in_array($page->id, $seenpages)) {
  126. $unseen[] = $page->id;
  127. }
  128. }
  129. if(count($unseen) == 0) {
  130. if(isset($pagesinbranch)) {
  131. $temp = end($pagesinbranch);
  132. $nextpage = $temp->nextpageid; // they have seen all the pages in the branch, so go to EOB/next branch table/EOL
  133. } else {
  134. // there are no pages inside the branch, so return the next page
  135. $nextpage = $lessonpages[$pageid]->nextpageid;
  136. }
  137. if ($nextpage == 0) {
  138. return LESSON_EOL;
  139. } else {
  140. return $nextpage;
  141. }
  142. } else {
  143. return $unseen[rand(0, count($unseen)-1)]; // returns a random page id for the next page
  144. }
  145. }
  146. /**
  147. * Handles the unseen branch table jump.
  148. *
  149. * @param lesson $lesson
  150. * @param int $userid User id.
  151. * @return int Will return the page id of a branch table or end of lesson
  152. **/
  153. function lesson_unseen_branch_jump($lesson, $userid) {
  154. global $DB;
  155. if (!$retakes = $DB->count_records("lesson_grades", array("lessonid"=>$lesson->id, "userid"=>$userid))) {
  156. $retakes = 0;
  157. }
  158. $params = array ("lessonid" => $lesson->id, "userid" => $userid, "retry" => $retakes);
  159. if (!$seenbranches = $DB->get_records_select("lesson_branch", "lessonid = :lessonid AND userid = :userid AND retry = :retry", $params,
  160. "timeseen DESC")) {
  161. print_error('cannotfindrecords', 'lesson');
  162. }
  163. // get the lesson pages
  164. $lessonpages = $lesson->load_all_pages();
  165. // this loads all the viewed branch tables into $seen until it finds the branch table with the flag
  166. // which is the branch table that starts the unseenbranch function
  167. $seen = array();
  168. foreach ($seenbranches as $seenbranch) {
  169. if (!$seenbranch->flag) {
  170. $seen[$seenbranch->pageid] = $seenbranch->pageid;
  171. } else {
  172. $start = $seenbranch->pageid;
  173. break;
  174. }
  175. }
  176. // this function searches through the lesson pages to find all the branch tables
  177. // that follow the flagged branch table
  178. $pageid = $lessonpages[$start]->nextpageid; // move down from the flagged branch table
  179. $branchtables = array();
  180. while ($pageid != 0) { // grab all of the branch table till eol
  181. if ($lessonpages[$pageid]->qtype == LESSON_PAGE_BRANCHTABLE) {
  182. $branchtables[] = $lessonpages[$pageid]->id;
  183. }
  184. $pageid = $lessonpages[$pageid]->nextpageid;
  185. }
  186. $unseen = array();
  187. foreach ($branchtables as $branchtable) {
  188. // load all of the unseen branch tables into unseen
  189. if (!array_key_exists($branchtable, $seen)) {
  190. $unseen[] = $branchtable;
  191. }
  192. }
  193. if (count($unseen) > 0) {
  194. return $unseen[rand(0, count($unseen)-1)]; // returns a random page id for the next page
  195. } else {
  196. return LESSON_EOL; // has viewed all of the branch tables
  197. }
  198. }
  199. /**
  200. * Handles the random jump between a branch table and end of branch or end of lesson (LESSON_RANDOMPAGE).
  201. *
  202. * @param lesson $lesson
  203. * @param int $pageid The id of the page that we are jumping from (?)
  204. * @return int The pageid of a random page that is within a branch table
  205. **/
  206. function lesson_random_question_jump($lesson, $pageid) {
  207. global $DB;
  208. // get the lesson pages
  209. $params = array ("lessonid" => $lesson->id);
  210. if (!$lessonpages = $DB->get_records_select("lesson_pages", "lessonid = :lessonid", $params)) {
  211. print_error('cannotfindpages', 'lesson');
  212. }
  213. // go up the pages till branch table
  214. while ($pageid != 0) { // this condition should never be satisfied... only happens if there are no branch tables above this page
  215. if ($lessonpages[$pageid]->qtype == LESSON_PAGE_BRANCHTABLE) {
  216. break;
  217. }
  218. $pageid = $lessonpages[$pageid]->prevpageid;
  219. }
  220. // get the pages within the branch
  221. $pagesinbranch = $lesson->get_sub_pages_of($pageid, array(LESSON_PAGE_BRANCHTABLE, LESSON_PAGE_ENDOFBRANCH));
  222. if(count($pagesinbranch) == 0) {
  223. // there are no pages inside the branch, so return the next page
  224. return $lessonpages[$pageid]->nextpageid;
  225. } else {
  226. return $pagesinbranch[rand(0, count($pagesinbranch)-1)]->id; // returns a random page id for the next page
  227. }
  228. }
  229. /**
  230. * Calculates a user's grade for a lesson.
  231. *
  232. * @param object $lesson The lesson that the user is taking.
  233. * @param int $retries The attempt number.
  234. * @param int $userid Id of the user (optional, default current user).
  235. * @return object { nquestions => number of questions answered
  236. attempts => number of question attempts
  237. total => max points possible
  238. earned => points earned by student
  239. grade => calculated percentage grade
  240. nmanual => number of manually graded questions
  241. manualpoints => point value for manually graded questions }
  242. */
  243. function lesson_grade($lesson, $ntries, $userid = 0) {
  244. global $USER, $DB;
  245. if (empty($userid)) {
  246. $userid = $USER->id;
  247. }
  248. // Zero out everything
  249. $ncorrect = 0;
  250. $nviewed = 0;
  251. $score = 0;
  252. $nmanual = 0;
  253. $manualpoints = 0;
  254. $thegrade = 0;
  255. $nquestions = 0;
  256. $total = 0;
  257. $earned = 0;
  258. $params = array ("lessonid" => $lesson->id, "userid" => $userid, "retry" => $ntries);
  259. if ($useranswers = $DB->get_records_select("lesson_attempts", "lessonid = :lessonid AND
  260. userid = :userid AND retry = :retry", $params, "timeseen")) {
  261. // group each try with its page
  262. $attemptset = array();
  263. foreach ($useranswers as $useranswer) {
  264. $attemptset[$useranswer->pageid][] = $useranswer;
  265. }
  266. // Drop all attempts that go beyond max attempts for the lesson
  267. foreach ($attemptset as $key => $set) {
  268. $attemptset[$key] = array_slice($set, 0, $lesson->maxattempts);
  269. }
  270. // get only the pages and their answers that the user answered
  271. list($usql, $parameters) = $DB->get_in_or_equal(array_keys($attemptset));
  272. array_unshift($parameters, $lesson->id);
  273. $pages = $DB->get_records_select("lesson_pages", "lessonid = ? AND id $usql", $parameters);
  274. $answers = $DB->get_records_select("lesson_answers", "lessonid = ? AND pageid $usql", $parameters);
  275. // Number of pages answered
  276. $nquestions = count($pages);
  277. foreach ($attemptset as $attempts) {
  278. $page = lesson_page::load($pages[end($attempts)->pageid], $lesson);
  279. if ($lesson->custom) {
  280. $attempt = end($attempts);
  281. // If essay question, handle it, otherwise add to score
  282. if ($page->requires_manual_grading()) {
  283. $useranswerobj = unserialize($attempt->useranswer);
  284. if (isset($useranswerobj->score)) {
  285. $earned += $useranswerobj->score;
  286. }
  287. $nmanual++;
  288. $manualpoints += $answers[$attempt->answerid]->score;
  289. } else if (!empty($attempt->answerid)) {
  290. $earned += $page->earned_score($answers, $attempt);
  291. }
  292. } else {
  293. foreach ($attempts as $attempt) {
  294. $earned += $attempt->correct;
  295. }
  296. $attempt = end($attempts); // doesn't matter which one
  297. // If essay question, increase numbers
  298. if ($page->requires_manual_grading()) {
  299. $nmanual++;
  300. $manualpoints++;
  301. }
  302. }
  303. // Number of times answered
  304. $nviewed += count($attempts);
  305. }
  306. if ($lesson->custom) {
  307. $bestscores = array();
  308. // Find the highest possible score per page to get our total
  309. foreach ($answers as $answer) {
  310. if(!isset($bestscores[$answer->pageid])) {
  311. $bestscores[$answer->pageid] = $answer->score;
  312. } else if ($bestscores[$answer->pageid] < $answer->score) {
  313. $bestscores[$answer->pageid] = $answer->score;
  314. }
  315. }
  316. $total = array_sum($bestscores);
  317. } else {
  318. // Check to make sure the student has answered the minimum questions
  319. if ($lesson->minquestions and $nquestions < $lesson->minquestions) {
  320. // Nope, increase number viewed by the amount of unanswered questions
  321. $total = $nviewed + ($lesson->minquestions - $nquestions);
  322. } else {
  323. $total = $nviewed;
  324. }
  325. }
  326. }
  327. if ($total) { // not zero
  328. $thegrade = round(100 * $earned / $total, 5);
  329. }
  330. // Build the grade information object
  331. $gradeinfo = new stdClass;
  332. $gradeinfo->nquestions = $nquestions;
  333. $gradeinfo->attempts = $nviewed;
  334. $gradeinfo->total = $total;
  335. $gradeinfo->earned = $earned;
  336. $gradeinfo->grade = $thegrade;
  337. $gradeinfo->nmanual = $nmanual;
  338. $gradeinfo->manualpoints = $manualpoints;
  339. return $gradeinfo;
  340. }
  341. /**
  342. * Determines if a user can view the left menu. The determining factor
  343. * is whether a user has a grade greater than or equal to the lesson setting
  344. * of displayleftif
  345. *
  346. * @param object $lesson Lesson object of the current lesson
  347. * @return boolean 0 if the user cannot see, or $lesson->displayleft to keep displayleft unchanged
  348. **/
  349. function lesson_displayleftif($lesson) {
  350. global $CFG, $USER, $DB;
  351. if (!empty($lesson->displayleftif)) {
  352. // get the current user's max grade for this lesson
  353. $params = array ("userid" => $USER->id, "lessonid" => $lesson->id);
  354. if ($maxgrade = $DB->get_record_sql('SELECT userid, MAX(grade) AS maxgrade FROM {lesson_grades} WHERE userid = :userid AND lessonid = :lessonid GROUP BY userid', $params)) {
  355. if ($maxgrade->maxgrade < $lesson->displayleftif) {
  356. return 0; // turn off the displayleft
  357. }
  358. } else {
  359. return 0; // no grades
  360. }
  361. }
  362. // if we get to here, keep the original state of displayleft lesson setting
  363. return $lesson->displayleft;
  364. }
  365. /**
  366. *
  367. * @param $cm
  368. * @param $lesson
  369. * @param $page
  370. * @return unknown_type
  371. */
  372. function lesson_add_fake_blocks($page, $cm, $lesson, $timer = null) {
  373. $bc = lesson_menu_block_contents($cm->id, $lesson);
  374. if (!empty($bc)) {
  375. $regions = $page->blocks->get_regions();
  376. $firstregion = reset($regions);
  377. $page->blocks->add_fake_block($bc, $firstregion);
  378. }
  379. $bc = lesson_mediafile_block_contents($cm->id, $lesson);
  380. if (!empty($bc)) {
  381. $page->blocks->add_fake_block($bc, $page->blocks->get_default_region());
  382. }
  383. if (!empty($timer)) {
  384. $bc = lesson_clock_block_contents($cm->id, $lesson, $timer, $page);
  385. if (!empty($bc)) {
  386. $page->blocks->add_fake_block($bc, $page->blocks->get_default_region());
  387. }
  388. }
  389. }
  390. /**
  391. * If there is a media file associated with this
  392. * lesson, return a block_contents that displays it.
  393. *
  394. * @param int $cmid Course Module ID for this lesson
  395. * @param object $lesson Full lesson record object
  396. * @return block_contents
  397. **/
  398. function lesson_mediafile_block_contents($cmid, $lesson) {
  399. global $OUTPUT;
  400. if (empty($lesson->mediafile)) {
  401. return null;
  402. }
  403. $options = array();
  404. $options['menubar'] = 0;
  405. $options['location'] = 0;
  406. $options['left'] = 5;
  407. $options['top'] = 5;
  408. $options['scrollbars'] = 1;
  409. $options['resizable'] = 1;
  410. $options['width'] = $lesson->mediawidth;
  411. $options['height'] = $lesson->mediaheight;
  412. $link = new moodle_url('/mod/lesson/mediafile.php?id='.$cmid);
  413. $action = new popup_action('click', $link, 'lessonmediafile', $options);
  414. $content = $OUTPUT->action_link($link, get_string('mediafilepopup', 'lesson'), $action, array('title'=>get_string('mediafilepopup', 'lesson')));
  415. $bc = new block_contents();
  416. $bc->title = get_string('linkedmedia', 'lesson');
  417. $bc->attributes['class'] = 'mediafile';
  418. $bc->content = $content;
  419. return $bc;
  420. }
  421. /**
  422. * If a timed lesson and not a teacher, then
  423. * return a block_contents containing the clock.
  424. *
  425. * @param int $cmid Course Module ID for this lesson
  426. * @param object $lesson Full lesson record object
  427. * @param object $timer Full timer record object
  428. * @return block_contents
  429. **/
  430. function lesson_clock_block_contents($cmid, $lesson, $timer, $page) {
  431. // Display for timed lessons and for students only
  432. $context = context_module::instance($cmid);
  433. if(!$lesson->timed || has_capability('mod/lesson:manage', $context)) {
  434. return null;
  435. }
  436. $content = '<div class="jshidewhenenabled">';
  437. $content .= $lesson->time_remaining($timer->starttime);
  438. $content .= '</div>';
  439. $clocksettings = array('starttime'=>$timer->starttime, 'servertime'=>time(),'testlength'=>($lesson->maxtime * 60));
  440. $page->requires->data_for_js('clocksettings', $clocksettings);
  441. $page->requires->js('/mod/lesson/timer.js');
  442. $page->requires->js_function_call('show_clock');
  443. $bc = new block_contents();
  444. $bc->title = get_string('timeremaining', 'lesson');
  445. $bc->attributes['class'] = 'clock block';
  446. $bc->content = $content;
  447. return $bc;
  448. }
  449. /**
  450. * If left menu is turned on, then this will
  451. * print the menu in a block
  452. *
  453. * @param int $cmid Course Module ID for this lesson
  454. * @param lesson $lesson Full lesson record object
  455. * @return void
  456. **/
  457. function lesson_menu_block_contents($cmid, $lesson) {
  458. global $CFG, $DB;
  459. if (!$lesson->displayleft) {
  460. return null;
  461. }
  462. $pages = $lesson->load_all_pages();
  463. foreach ($pages as $page) {
  464. if ((int)$page->prevpageid === 0) {
  465. $pageid = $page->id;
  466. break;
  467. }
  468. }
  469. $currentpageid = optional_param('pageid', $pageid, PARAM_INT);
  470. if (!$pageid || !$pages) {
  471. return null;
  472. }
  473. $content = '<a href="#maincontent" class="skip">'.get_string('skip', 'lesson')."</a>\n<div class=\"menuwrapper\">\n<ul>\n";
  474. while ($pageid != 0) {
  475. $page = $pages[$pageid];
  476. // Only process branch tables with display turned on
  477. if ($page->displayinmenublock && $page->display) {
  478. if ($page->id == $currentpageid) {
  479. $content .= '<li class="selected">'.format_string($page->title,true)."</li>\n";
  480. } else {
  481. $content .= "<li class=\"notselected\"><a href=\"$CFG->wwwroot/mod/lesson/view.php?id=$cmid&amp;pageid=$page->id\">".format_string($page->title,true)."</a></li>\n";
  482. }
  483. }
  484. $pageid = $page->nextpageid;
  485. }
  486. $content .= "</ul>\n</div>\n";
  487. $bc = new block_contents();
  488. $bc->title = get_string('lessonmenu', 'lesson');
  489. $bc->attributes['class'] = 'menu block';
  490. $bc->content = $content;
  491. return $bc;
  492. }
  493. /**
  494. * Adds header buttons to the page for the lesson
  495. *
  496. * @param object $cm
  497. * @param object $context
  498. * @param bool $extraeditbuttons
  499. * @param int $lessonpageid
  500. */
  501. function lesson_add_header_buttons($cm, $context, $extraeditbuttons=false, $lessonpageid=null) {
  502. global $CFG, $PAGE, $OUTPUT;
  503. if (has_capability('mod/lesson:edit', $context) && $extraeditbuttons) {
  504. if ($lessonpageid === null) {
  505. print_error('invalidpageid', 'lesson');
  506. }
  507. if (!empty($lessonpageid) && $lessonpageid != LESSON_EOL) {
  508. $url = new moodle_url('/mod/lesson/editpage.php', array('id'=>$cm->id, 'pageid'=>$lessonpageid, 'edit'=>1));
  509. $PAGE->set_button($OUTPUT->single_button($url, get_string('editpagecontent', 'lesson')));
  510. }
  511. }
  512. }
  513. /**
  514. * This is a function used to detect media types and generate html code.
  515. *
  516. * @global object $CFG
  517. * @global object $PAGE
  518. * @param object $lesson
  519. * @param object $context
  520. * @return string $code the html code of media
  521. */
  522. function lesson_get_media_html($lesson, $context) {
  523. global $CFG, $PAGE, $OUTPUT;
  524. require_once("$CFG->libdir/resourcelib.php");
  525. // get the media file link
  526. if (strpos($lesson->mediafile, '://') !== false) {
  527. $url = new moodle_url($lesson->mediafile);
  528. } else {
  529. // the timemodified is used to prevent caching problems, instead of '/' we should better read from files table and use sortorder
  530. $url = moodle_url::make_pluginfile_url($context->id, 'mod_lesson', 'mediafile', $lesson->timemodified, '/', ltrim($lesson->mediafile, '/'));
  531. }
  532. $title = $lesson->mediafile;
  533. $clicktoopen = html_writer::link($url, get_string('download'));
  534. $mimetype = resourcelib_guess_url_mimetype($url);
  535. $extension = resourcelib_get_extension($url->out(false));
  536. $mediarenderer = $PAGE->get_renderer('core', 'media');
  537. $embedoptions = array(
  538. core_media::OPTION_TRUSTED => true,
  539. core_media::OPTION_BLOCK => true
  540. );
  541. // find the correct type and print it out
  542. if (in_array($mimetype, array('image/gif','image/jpeg','image/png'))) { // It's an image
  543. $code = resourcelib_embed_image($url, $title);
  544. } else if ($mediarenderer->can_embed_url($url, $embedoptions)) {
  545. // Media (audio/video) file.
  546. $code = $mediarenderer->embed_url($url, $title, 0, 0, $embedoptions);
  547. } else {
  548. // anything else - just try object tag enlarged as much as possible
  549. $code = resourcelib_embed_general($url, $title, $clicktoopen, $mimetype);
  550. }
  551. return $code;
  552. }
  553. /**
  554. * Abstract class that page type's MUST inherit from.
  555. *
  556. * This is the abstract class that ALL add page type forms must extend.
  557. * You will notice that all but two of the methods this class contains are final.
  558. * Essentially the only thing that extending classes can do is extend custom_definition.
  559. * OR if it has a special requirement on creation it can extend construction_override
  560. *
  561. * @abstract
  562. * @copyright 2009 Sam Hemelryk
  563. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  564. */
  565. abstract class lesson_add_page_form_base extends moodleform {
  566. /**
  567. * This is the classic define that is used to identify this pagetype.
  568. * Will be one of LESSON_*
  569. * @var int
  570. */
  571. public $qtype;
  572. /**
  573. * The simple string that describes the page type e.g. truefalse, multichoice
  574. * @var string
  575. */
  576. public $qtypestring;
  577. /**
  578. * An array of options used in the htmleditor
  579. * @var array
  580. */
  581. protected $editoroptions = array();
  582. /**
  583. * True if this is a standard page of false if it does something special.
  584. * Questions are standard pages, branch tables are not
  585. * @var bool
  586. */
  587. protected $standard = true;
  588. /**
  589. * Each page type can and should override this to add any custom elements to
  590. * the basic form that they want
  591. */
  592. public function custom_definition() {}
  593. /**
  594. * Used to determine if this is a standard page or a special page
  595. * @return bool
  596. */
  597. public final function is_standard() {
  598. return (bool)$this->standard;
  599. }
  600. /**
  601. * Add the required basic elements to the form.
  602. *
  603. * This method adds the basic elements to the form including title and contents
  604. * and then calls custom_definition();
  605. */
  606. public final function definition() {
  607. $mform = $this->_form;
  608. $editoroptions = $this->_customdata['editoroptions'];
  609. $mform->addElement('header', 'qtypeheading', get_string('createaquestionpage', 'lesson', get_string($this->qtypestring, 'lesson')));
  610. $mform->addElement('hidden', 'id');
  611. $mform->setType('id', PARAM_INT);
  612. $mform->addElement('hidden', 'pageid');
  613. $mform->setType('pageid', PARAM_INT);
  614. if ($this->standard === true) {
  615. $mform->addElement('hidden', 'qtype');
  616. $mform->setType('qtype', PARAM_INT);
  617. $mform->addElement('text', 'title', get_string('pagetitle', 'lesson'), array('size'=>70));
  618. $mform->setType('title', PARAM_TEXT);
  619. $mform->addRule('title', get_string('required'), 'required', null, 'client');
  620. $this->editoroptions = array('noclean'=>true, 'maxfiles'=>EDITOR_UNLIMITED_FILES, 'maxbytes'=>$this->_customdata['maxbytes']);
  621. $mform->addElement('editor', 'contents_editor', get_string('pagecontents', 'lesson'), null, $this->editoroptions);
  622. $mform->setType('contents_editor', PARAM_RAW);
  623. $mform->addRule('contents_editor', get_string('required'), 'required', null, 'client');
  624. }
  625. $this->custom_definition();
  626. if ($this->_customdata['edit'] === true) {
  627. $mform->addElement('hidden', 'edit', 1);
  628. $mform->setType('edit', PARAM_BOOL);
  629. $this->add_action_buttons(get_string('cancel'), get_string('savepage', 'lesson'));
  630. } else if ($this->qtype === 'questiontype') {
  631. $this->add_action_buttons(get_string('cancel'), get_string('addaquestionpage', 'lesson'));
  632. } else {
  633. $this->add_action_buttons(get_string('cancel'), get_string('savepage', 'lesson'));
  634. }
  635. }
  636. /**
  637. * Convenience function: Adds a jumpto select element
  638. *
  639. * @param string $name
  640. * @param string|null $label
  641. * @param int $selected The page to select by default
  642. */
  643. protected final function add_jumpto($name, $label=null, $selected=LESSON_NEXTPAGE) {
  644. $title = get_string("jump", "lesson");
  645. if ($label === null) {
  646. $label = $title;
  647. }
  648. if (is_int($name)) {
  649. $name = "jumpto[$name]";
  650. }
  651. $this->_form->addElement('select', $name, $label, $this->_customdata['jumpto']);
  652. $this->_form->setDefault($name, $selected);
  653. $this->_form->addHelpButton($name, 'jumps', 'lesson');
  654. }
  655. /**
  656. * Convenience function: Adds a score input element
  657. *
  658. * @param string $name
  659. * @param string|null $label
  660. * @param mixed $value The default value
  661. */
  662. protected final function add_score($name, $label=null, $value=null) {
  663. if ($label === null) {
  664. $label = get_string("score", "lesson");
  665. }
  666. if (is_int($name)) {
  667. $name = "score[$name]";
  668. }
  669. $this->_form->addElement('text', $name, $label, array('size'=>5));
  670. $this->_form->setType($name, PARAM_INT);
  671. if ($value !== null) {
  672. $this->_form->setDefault($name, $value);
  673. }
  674. $this->_form->addHelpButton($name, 'score', 'lesson');
  675. // Score is only used for custom scoring. Disable the element when not in use to stop some confusion.
  676. if (!$this->_customdata['lesson']->custom) {
  677. $this->_form->freeze($name);
  678. }
  679. }
  680. /**
  681. * Convenience function: Adds an answer editor
  682. *
  683. * @param int $count The count of the element to add
  684. * @param string $label, null means default
  685. * @param bool $required
  686. * @return void
  687. */
  688. protected final function add_answer($count, $label = null, $required = false) {
  689. if ($label === null) {
  690. $label = get_string('answer', 'lesson');
  691. }
  692. $this->_form->addElement('editor', 'answer_editor['.$count.']', $label, array('rows'=>'4', 'columns'=>'80'), array('noclean'=>true));
  693. $this->_form->setDefault('answer_editor['.$count.']', array('text'=>'', 'format'=>FORMAT_MOODLE));
  694. if ($required) {
  695. $this->_form->addRule('answer_editor['.$count.']', get_string('required'), 'required', null, 'client');
  696. }
  697. }
  698. /**
  699. * Convenience function: Adds an response editor
  700. *
  701. * @param int $count The count of the element to add
  702. * @param string $label, null means default
  703. * @param bool $required
  704. * @return void
  705. */
  706. protected final function add_response($count, $label = null, $required = false) {
  707. if ($label === null) {
  708. $label = get_string('response', 'lesson');
  709. }
  710. $this->_form->addElement('editor', 'response_editor['.$count.']', $label, array('rows'=>'4', 'columns'=>'80'), array('noclean'=>true));
  711. $this->_form->setDefault('response_editor['.$count.']', array('text'=>'', 'format'=>FORMAT_MOODLE));
  712. if ($required) {
  713. $this->_form->addRule('response_editor['.$count.']', get_string('required'), 'required', null, 'client');
  714. }
  715. }
  716. /**
  717. * A function that gets called upon init of this object by the calling script.
  718. *
  719. * This can be used to process an immediate action if required. Currently it
  720. * is only used in special cases by non-standard page types.
  721. *
  722. * @return bool
  723. */
  724. public function construction_override($pageid, lesson $lesson) {
  725. return true;
  726. }
  727. }
  728. /**
  729. * Class representation of a lesson
  730. *
  731. * This class is used the interact with, and manage a lesson once instantiated.
  732. * If you need to fetch a lesson object you can do so by calling
  733. *
  734. * <code>
  735. * lesson::load($lessonid);
  736. * // or
  737. * $lessonrecord = $DB->get_record('lesson', $lessonid);
  738. * $lesson = new lesson($lessonrecord);
  739. * </code>
  740. *
  741. * The class itself extends lesson_base as all classes within the lesson module should
  742. *
  743. * These properties are from the database
  744. * @property int $id The id of this lesson
  745. * @property int $course The ID of the course this lesson belongs to
  746. * @property string $name The name of this lesson
  747. * @property int $practice Flag to toggle this as a practice lesson
  748. * @property int $modattempts Toggle to allow the user to go back and review answers
  749. * @property int $usepassword Toggle the use of a password for entry
  750. * @property string $password The password to require users to enter
  751. * @property int $dependency ID of another lesson this lesson is dependent on
  752. * @property string $conditions Conditions of the lesson dependency
  753. * @property int $grade The maximum grade a user can achieve (%)
  754. * @property int $custom Toggle custom scoring on or off
  755. * @property int $ongoing Toggle display of an ongoing score
  756. * @property int $usemaxgrade How retakes are handled (max=1, mean=0)
  757. * @property int $maxanswers The max number of answers or branches
  758. * @property int $maxattempts The maximum number of attempts a user can record
  759. * @property int $review Toggle use or wrong answer review button
  760. * @property int $nextpagedefault Override the default next page
  761. * @property int $feedback Toggles display of default feedback
  762. * @property int $minquestions Sets a minimum value of pages seen when calculating grades
  763. * @property int $maxpages Maximum number of pages this lesson can contain
  764. * @property int $retake Flag to allow users to retake a lesson
  765. * @property int $activitylink Relate this lesson to another lesson
  766. * @property string $mediafile File to pop up to or webpage to display
  767. * @property int $mediaheight Sets the height of the media file popup
  768. * @property int $mediawidth Sets the width of the media file popup
  769. * @property int $mediaclose Toggle display of a media close button
  770. * @property int $slideshow Flag for whether branch pages should be shown as slideshows
  771. * @property int $width Width of slideshow
  772. * @property int $height Height of slideshow
  773. * @property string $bgcolor Background colour of slideshow
  774. * @property int $displayleft Display a left menu
  775. * @property int $displayleftif Sets the condition on which the left menu is displayed
  776. * @property int $progressbar Flag to toggle display of a lesson progress bar
  777. * @property int $highscores Flag to toggle collection of high scores
  778. * @property int $maxhighscores Number of high scores to limit to
  779. * @property int $available Timestamp of when this lesson becomes available
  780. * @property int $deadline Timestamp of when this lesson is no longer available
  781. * @property int $timemodified Timestamp when lesson was last modified
  782. *
  783. * These properties are calculated
  784. * @property int $firstpageid Id of the first page of this lesson (prevpageid=0)
  785. * @property int $lastpageid Id of the last page of this lesson (nextpageid=0)
  786. *
  787. * @copyright 2009 Sam Hemelryk
  788. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  789. */
  790. class lesson extends lesson_base {
  791. /**
  792. * The id of the first page (where prevpageid = 0) gets set and retrieved by
  793. * {@see get_firstpageid()} by directly calling <code>$lesson->firstpageid;</code>
  794. * @var int
  795. */
  796. protected $firstpageid = null;
  797. /**
  798. * The id of the last page (where nextpageid = 0) gets set and retrieved by
  799. * {@see get_lastpageid()} by directly calling <code>$lesson->lastpageid;</code>
  800. * @var int
  801. */
  802. protected $lastpageid = null;
  803. /**
  804. * An array used to cache the pages associated with this lesson after the first
  805. * time they have been loaded.
  806. * A note to developers: If you are going to be working with MORE than one or
  807. * two pages from a lesson you should probably call {@see $lesson->load_all_pages()}
  808. * in order to save excess database queries.
  809. * @var array An array of lesson_page objects
  810. */
  811. protected $pages = array();
  812. /**
  813. * Flag that gets set to true once all of the pages associated with the lesson
  814. * have been loaded.
  815. * @var bool
  816. */
  817. protected $loadedallpages = false;
  818. /**
  819. * Simply generates a lesson object given an array/object of properties
  820. * Overrides {@see lesson_base->create()}
  821. * @static
  822. * @param object|array $properties
  823. * @return lesson
  824. */
  825. public static function create($properties) {
  826. return new lesson($properties);
  827. }
  828. /**
  829. * Generates a lesson object from the database given its id
  830. * @static
  831. * @param int $lessonid
  832. * @return lesson
  833. */
  834. public static function load($lessonid) {
  835. global $DB;
  836. if (!$lesson = $DB->get_record('lesson', array('id' => $lessonid))) {
  837. print_error('invalidcoursemodule');
  838. }
  839. return new lesson($lesson);
  840. }
  841. /**
  842. * Deletes this lesson from the database
  843. */
  844. public function delete() {
  845. global $CFG, $DB;
  846. require_once($CFG->libdir.'/gradelib.php');
  847. require_once($CFG->dirroot.'/calendar/lib.php');
  848. $cm = get_coursemodule_from_instance('lesson', $this->properties->id, $this->properties->course);
  849. $context = context_module::instance($cm->id);
  850. $DB->delete_records("lesson", array("id"=>$this->properties->id));
  851. $DB->delete_records("lesson_pages", array("lessonid"=>$this->properties->id));
  852. $DB->delete_records("lesson_answers", array("lessonid"=>$this->properties->id));
  853. $DB->delete_records("lesson_attempts", array("lessonid"=>$this->properties->id));
  854. $DB->delete_records("lesson_grades", array("lessonid"=>$this->properties->id));
  855. $DB->delete_records("lesson_timer", array("lessonid"=>$this->properties->id));
  856. $DB->delete_records("lesson_branch", array("lessonid"=>$this->properties->id));
  857. $DB->delete_records("lesson_high_scores", array("lessonid"=>$this->properties->id));
  858. if ($events = $DB->get_records('event', array("modulename"=>'lesson', "instance"=>$this->properties->id))) {
  859. foreach($events as $event) {
  860. $event = calendar_event::load($event);
  861. $event->delete();
  862. }
  863. }
  864. // Delete files associated with this module.
  865. $fs = get_file_storage();
  866. $fs->delete_area_files($context->id);
  867. grade_update('mod/lesson', $this->properties->course, 'mod', 'lesson', $this->properties->id, 0, null, array('deleted'=>1));
  868. return true;
  869. }
  870. /**
  871. * Fetches messages from the session that may have been set in previous page
  872. * actions.
  873. *
  874. * <code>
  875. * // Do not call this method directly instead use
  876. * $lesson->messages;
  877. * </code>
  878. *
  879. * @return array
  880. */
  881. protected function get_messages() {
  882. global $SESSION;
  883. $messages = array();
  884. if (!empty($SESSION->lesson_messages) && is_array($SESSION->lesson_messages) && array_key_exists($this->properties->id, $SESSION->lesson_messages)) {
  885. $messages = $SESSION->lesson_messages[$this->properties->id];
  886. unset($SESSION->lesson_messages[$this->properties->id]);
  887. }
  888. return $messages;
  889. }
  890. /**
  891. * Get all of the attempts for the current user.
  892. *
  893. * @param int $retries
  894. * @param bool $correct Optional: only fetch correct attempts
  895. * @param int $pageid Optional: only fetch attempts at the given page
  896. * @param int $userid Optional: defaults to the current user if not set
  897. * @return array|false
  898. */
  899. public function get_attempts($retries, $correct=false, $pageid=null, $userid=null) {
  900. global $USER, $DB;
  901. $params = array("lessonid"=>$this->properties->id, "userid"=>$userid, "retry"=>$retries);
  902. if ($correct) {
  903. $params['correct'] = 1;
  904. }
  905. if ($pageid !== null) {
  906. $params['pageid'] = $pageid;
  907. }
  908. if ($userid === null) {
  909. $params['userid'] = $USER->id;
  910. }
  911. return $DB->get_records('lesson_attempts', $params, 'timeseen ASC');
  912. }
  913. /**
  914. * Returns the first page for the lesson or false if there isn't one.
  915. *
  916. * This method should be called via the magic method __get();
  917. * <code>
  918. * $firstpage = $lesson->firstpage;
  919. * </code>
  920. *
  921. * @return lesson_page|bool Returns the lesson_page specialised object or false
  922. */
  923. protected function get_firstpage() {
  924. $pages = $this->load_all_pages();
  925. if (count($pages) > 0) {
  926. foreach ($pages as $page) {
  927. if ((int)$page->prevpageid === 0) {
  928. return $page;
  929. }
  930. }
  931. }
  932. return false;
  933. }
  934. /**
  935. * Returns the last page for the lesson or false if there isn't one.
  936. *
  937. * This method should be called via the magic method __get();
  938. * <code>
  939. * $lastpage = $lesson->lastpage;
  940. * </code>
  941. *
  942. * @return lesson_page|bool Returns the lesson_page specialised object or false
  943. */
  944. protected function get_lastpage() {
  945. $pages = $this->load_all_pages();
  946. if (count($pages) > 0) {
  947. foreach ($pages as $page) {
  948. if ((int)$page->nextpageid === 0) {
  949. return $page;
  950. }
  951. }
  952. }
  953. return false;
  954. }
  955. /**
  956. * Returns the id of the first page of this lesson. (prevpageid = 0)
  957. * @return int
  958. */
  959. protected function get_firstpageid() {
  960. global $DB;
  961. if ($this->firstpageid == null) {
  962. if (!$this->loadedallpages) {
  963. $firstpageid = $DB->get_field('lesson_pages', 'id', array('lessonid'=>$this->properties->id, 'prevpageid'=>0));
  964. if (!$firstpageid) {
  965. print_error('cannotfindfirstpage', 'lesson');
  966. }
  967. $this->firstpageid = $firstpageid;
  968. } else {
  969. $firstpage = $this->get_firstpage();
  970. $this->firstpageid = $firstpage->id;
  971. }
  972. }
  973. return $this->firstpageid;
  974. }
  975. /**
  976. * Returns the id of the last page of this lesson. (nextpageid = 0)
  977. * @return int
  978. */
  979. public function get_lastpageid() {
  980. global $DB;
  981. if ($this->lastpageid == null) {
  982. if (!$this->loadedallpages) {
  983. $lastpageid = $DB->get_field('lesson_pages', 'id', array('lessonid'=>$this->properties->id, 'nextpageid'=>0));
  984. if (!$lastpageid) {
  985. print_error('cannotfindlastpage', 'lesson');
  986. }
  987. $this->lastpageid = $lastpageid;
  988. } else {
  989. $lastpageid = $this->get_lastpage();
  990. $this->lastpageid = $lastpageid->id;
  991. }
  992. }
  993. return $this->lastpageid;
  994. }
  995. /**
  996. * Gets the next page id to display after the one that is provided.
  997. * @param int $nextpageid
  998. * @return bool
  999. */
  1000. public function get_next_page($nextpageid) {
  1001. global $USER, $DB;
  1002. $allpages = $this->load_all_pages();
  1003. if ($this->properties->nextpagedefault) {
  1004. // in Flash Card mode...first get number of retakes
  1005. $nretakes = $DB->count_records("lesson_grades", array("lessonid" => $this->properties->id, "userid" => $USER->id));
  1006. shuffle($allpages);
  1007. $found = false;
  1008. if ($this->properties->nextpagedefault == LESSON_UNSEENPAGE) {
  1009. foreach ($allpages as $nextpage) {
  1010. if (!$DB->count_records("lesson_attempts", array("pageid" => $nextpage->id, "userid" => $USER->id, "retry" => $nretakes))) {
  1011. $found = true;
  1012. break;
  1013. }
  1014. }
  1015. } elseif ($this->properties->nextpagedefault == LESSON_UNANSWEREDPAGE) {
  1016. foreach ($allpages as $nextpage) {
  1017. if (!$DB->count_records("lesson_attempts", array('pageid' => $nextpage->id, 'userid' => $USER->id, 'correct' => 1, 'retry' => $nretakes))) {
  1018. $found = true;
  1019. break;
  1020. }
  1021. }
  1022. }
  1023. if ($found) {
  1024. if ($this->properties->maxpages) {
  1025. // check number of pages viewed (in the lesson)
  1026. if ($DB->count_records("lesson_attempts", array("lessonid" => $this->properties->id, "userid" => $USER->id, "retry" => $nretakes)) >= $this->properties->maxpages) {
  1027. return LESSON_EOL;
  1028. }
  1029. }
  1030. return $nextpage->id;
  1031. }
  1032. }
  1033. // In a normal lesson mode
  1034. foreach ($allpages as $nextpage) {
  1035. if ((int)$nextpage->id === (int)$nextpageid) {
  1036. return $nextpage->id;
  1037. }
  1038. }
  1039. return LESSON_EOL;
  1040. }
  1041. /**
  1042. * Sets a message against the session for this lesson that will displayed next
  1043. * time the lesson processes messages
  1044. *
  1045. * @param string $message
  1046. * @param string $class
  1047. * @param string $align
  1048. * @return bool
  1049. */
  1050. public function add_message($message, $class="notifyproblem", $align='center') {
  1051. global $SESSION;
  1052. if (empty($SESSION->lesson_messages) || !is_array($SESSION->lesson_messages)) {
  1053. $SESSION->lesson_messages = array();
  1054. $SESSION->lesson_messages[$this->properties->id] = array();
  1055. } else if (!array_key_exists($this->properties->id, $SESSION->lesson_messages)) {
  1056. $SESSION->lesson_messages[$this->properties->id] = array();
  1057. }
  1058. $SESSION->lesson_messages[$this->properties->id][] = array($message, $class, $align);
  1059. return true;
  1060. }
  1061. /**
  1062. * Check if the lesson is accessible at the present time
  1063. * @return bool True if the lesson is accessible, false otherwise
  1064. */
  1065. public function is_accessible() {
  1066. $available = $this->properties->available;
  1067. $deadline = $this->properties->deadline;
  1068. return (($available == 0 || time() >= $available) && ($deadline == 0 || time() < $deadline));
  1069. }
  1070. /**
  1071. * Starts the lesson time for the current user
  1072. * @return bool Returns true
  1073. */
  1074. public function start_timer() {
  1075. global $USER, $DB;
  1076. $USER->startlesson[$this->properties->id] = true;
  1077. $startlesson = new stdClass;
  1078. $startlesson->lessonid = $this->properties->id;
  1079. $startlesson->userid = $USER->id;
  1080. $startlesson->starttime = time();
  1081. $startlesson->lessontime = time();
  1082. $DB->insert_record('lesson_timer', $startlesson);
  1083. if ($this->properties->timed) {
  1084. $this->add_message(get_string('maxtimewarning', 'lesson', $this->properties->maxtime), 'center');
  1085. }
  1086. return true;
  1087. }
  1088. /**
  1089. * Updates the timer to the current time and returns the new timer object
  1090. * @param bool $restart If set to true the timer is restarted
  1091. * @param bool $continue If set to true AND $restart=true then the timer
  1092. * will continue from a previous attempt
  1093. * @return stdClass The new timer
  1094. */
  1095. public function update_timer($restart=false, $continue=false) {
  1096. global $USER, $DB;
  1097. // clock code
  1098. // get time information for this user
  1099. if (!$timer = $DB->get_records('lesson_timer', array ("lessonid" => $this->properties->id, "userid" => $USER->id), 'starttime DESC', '*', 0, 1)) {
  1100. print_error('cannotfindtimer', 'lesson');
  1101. } else {
  1102. $timer = current($timer); // this will get the latest start time record
  1103. }
  1104. if ($restart) {
  1105. if ($continue) {
  1106. // continue a previous test, need to update the clock (think this option is disabled atm)
  1107. $timer->starttime = time() - ($timer->lessontime - $timer->starttime);
  1108. } else {
  1109. // starting over, so reset the clock
  1110. $timer->starttime = time();
  1111. }
  1112. }
  1113. $timer->lessontime = time();
  1114. $DB->update_record('lesson_timer', $timer);
  1115. return $timer;
  1116. }
  1117. /**
  1118. * Updates the timer to the current time then stops it by unsetting the user var
  1119. * @return bool Returns true
  1120. */
  1121. public function stop_timer() {
  1122. global $USER, $DB;
  1123. unset($USER->startlesson[$this->properties->id]);
  1124. return $this->update_timer(false, false);
  1125. }
  1126. /**
  1127. * Checks to see if the lesson has pages
  1128. */
  1129. public function has_pages() {
  1130. global $DB;
  1131. $pagecount = $DB->count_records('lesson_pages', array('lessonid'=>$this->properties->id));
  1132. return ($pagecount>0);
  1133. }
  1134. /**
  1135. * Returns the link for the related activity
  1136. * @return array|false
  1137. */
  1138. public function link_for_activitylink() {
  1139. global $DB;
  1140. $module = $DB->get_record('course_modules', array('id' => $this->properties->activitylink));
  1141. if ($module) {
  1142. $modname = $DB->get_field('modules', 'name', array('id' => $module->module));
  1143. if ($modname) {
  1144. $instancename = $DB->get_field($modname, 'name', array('id' => $module->instance));
  1145. if ($instancename) {
  1146. return html_writer::link(new moodle_url('/mod/'.$modname.'/view.php', array('id'=>$this->properties->activitylink)),
  1147. get_string('activitylinkname', 'lesson', $instancename),
  1148. array('class'=>'centerpadded lessonbutton standardbutton'));
  1149. }
  1150. }
  1151. }
  1152. return '';
  1153. }
  1154. /**
  1155. * Loads the requested page.
  1156. *
  1157. * This function will return the requested page id as either a specialised
  1158. * lesson_page object OR as a generic lesson_page.
  1159. * If the page has been loaded previously it will be returned from the pages
  1160. * array, otherwise it will be loaded from the database first
  1161. *
  1162. * @param int $pageid
  1163. * @return lesson_page A lesson_page object or an object that extends it
  1164. */
  1165. public function load_page($pageid) {
  1166. if (!array_key_exists($pageid, $this->pages)) {
  1167. $manager = lesson_page_type_manager::get($this);
  1168. $this->pages[$pageid] = $manager->load_page($pageid, $this);
  1169. }
  1170. return $this->pages[$pageid];
  1171. }
  1172. /**
  1173. * Loads ALL of the pages for this lesson
  1174. *
  1175. * @return array An array containing all pages from this lesson
  1176. */
  1177. public function load_all_pages() {
  1178. if (!$this->loadedallpages) {
  1179. $manager = lesson_page_type_manager::get($this);
  1180. $this->pages = $manager->load_all_pages($this);
  1181. $this->loadedallpages = true;
  1182. }
  1183. return $this->pages;
  1184. }
  1185. /**
  1186. * Determines if a jumpto value is correct or not.
  1187. *
  1188. * returns true if jumpto page is (logically) after the pageid page or
  1189. * if the jumpto value is a special value. Returns false in all other cases.
  1190. *
  1191. * @param int $pageid Id of the page from which you are jumping from.
  1192. * @param int $jumpto The jumpto number.
  1193. * @return boolean True or false after a series of tests.
  1194. **/
  1195. public function jumpto_is_correct($pageid, $jumpto) {
  1196. global $DB;
  1197. // first test the special values
  1198. if (!$jumpto) {
  1199. // same page
  1200. return false;
  1201. } elseif ($jumpto == LESSON_NEXTPAGE) {
  1202. return true;
  1203. } elseif ($jumpto == LE

Large files files are truncated, but you can click here to view the full file