[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/mod/book/ -> lib.php (source)

   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  /**
  18   * Book module core interaction API
  19   *
  20   * @package    mod_book
  21   * @copyright  2004-2011 Petr Skoda {@link http://skodak.org}
  22   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23   */
  24  
  25  defined('MOODLE_INTERNAL') || die;
  26  
  27  /**
  28   * Returns list of available numbering types
  29   * @return array
  30   */
  31  function book_get_numbering_types() {
  32      global $CFG; // required for the include
  33  
  34      require_once (__DIR__.'/locallib.php');
  35  
  36      return array (
  37          BOOK_NUM_NONE       => get_string('numbering0', 'mod_book'),
  38          BOOK_NUM_NUMBERS    => get_string('numbering1', 'mod_book'),
  39          BOOK_NUM_BULLETS    => get_string('numbering2', 'mod_book'),
  40          BOOK_NUM_INDENTED   => get_string('numbering3', 'mod_book')
  41      );
  42  }
  43  
  44  /**
  45   * Returns list of available navigation link types.
  46   * @return array
  47   */
  48  function book_get_nav_types() {
  49      require_once (__DIR__.'/locallib.php');
  50  
  51      return array (
  52          BOOK_LINK_TOCONLY   => get_string('navtoc', 'mod_book'),
  53          BOOK_LINK_IMAGE     => get_string('navimages', 'mod_book'),
  54          BOOK_LINK_TEXT      => get_string('navtext', 'mod_book'),
  55      );
  56  }
  57  
  58  /**
  59   * Returns list of available navigation link CSS classes.
  60   * @return array
  61   */
  62  function book_get_nav_classes() {
  63      return array ('navtoc', 'navimages', 'navtext');
  64  }
  65  
  66  /**
  67   * Returns all other caps used in module
  68   * @return array
  69   */
  70  function book_get_extra_capabilities() {
  71      // used for group-members-only
  72      return array('moodle/site:accessallgroups');
  73  }
  74  
  75  /**
  76   * Add book instance.
  77   *
  78   * @param stdClass $data
  79   * @param stdClass $mform
  80   * @return int new book instance id
  81   */
  82  function book_add_instance($data, $mform) {
  83      global $DB;
  84  
  85      $data->timecreated = time();
  86      $data->timemodified = $data->timecreated;
  87      if (!isset($data->customtitles)) {
  88          $data->customtitles = 0;
  89      }
  90  
  91      return $DB->insert_record('book', $data);
  92  }
  93  
  94  /**
  95   * Update book instance.
  96   *
  97   * @param stdClass $data
  98   * @param stdClass $mform
  99   * @return bool true
 100   */
 101  function book_update_instance($data, $mform) {
 102      global $DB;
 103  
 104      $data->timemodified = time();
 105      $data->id = $data->instance;
 106      if (!isset($data->customtitles)) {
 107          $data->customtitles = 0;
 108      }
 109  
 110      $DB->update_record('book', $data);
 111  
 112      $book = $DB->get_record('book', array('id'=>$data->id));
 113      $DB->set_field('book', 'revision', $book->revision+1, array('id'=>$book->id));
 114  
 115      return true;
 116  }
 117  
 118  /**
 119   * Delete book instance by activity id
 120   *
 121   * @param int $id
 122   * @return bool success
 123   */
 124  function book_delete_instance($id) {
 125      global $DB;
 126  
 127      if (!$book = $DB->get_record('book', array('id'=>$id))) {
 128          return false;
 129      }
 130  
 131      $DB->delete_records('book_chapters', array('bookid'=>$book->id));
 132      $DB->delete_records('book', array('id'=>$book->id));
 133  
 134      return true;
 135  }
 136  
 137  /**
 138   * Given a course and a time, this module should find recent activity
 139   * that has occurred in book activities and print it out.
 140   *
 141   * @param stdClass $course
 142   * @param bool $viewfullnames
 143   * @param int $timestart
 144   * @return bool true if there was output, or false is there was none
 145   */
 146  function book_print_recent_activity($course, $viewfullnames, $timestart) {
 147      return false;  //  True if anything was printed, otherwise false
 148  }
 149  
 150  /**
 151   * This function is used by the reset_course_userdata function in moodlelib.
 152   * @param $data the data submitted from the reset course.
 153   * @return array status array
 154   */
 155  function book_reset_userdata($data) {
 156      return array();
 157  }
 158  
 159  /**
 160   * No cron in book.
 161   *
 162   * @return bool
 163   */
 164  function book_cron () {
 165      return true;
 166  }
 167  
 168  /**
 169   * No grading in book.
 170   *
 171   * @param int $bookid
 172   * @return null
 173   */
 174  function book_grades($bookid) {
 175      return null;
 176  }
 177  
 178  /**
 179   * This function returns if a scale is being used by one book
 180   * it it has support for grading and scales. Commented code should be
 181   * modified if necessary. See book, glossary or journal modules
 182   * as reference.
 183   *
 184   * @param int $bookid
 185   * @param int $scaleid
 186   * @return boolean True if the scale is used by any journal
 187   */
 188  function book_scale_used($bookid, $scaleid) {
 189      return false;
 190  }
 191  
 192  /**
 193   * Checks if scale is being used by any instance of book
 194   *
 195   * This is used to find out if scale used anywhere
 196   *
 197   * @param int $scaleid
 198   * @return bool true if the scale is used by any book
 199   */
 200  function book_scale_used_anywhere($scaleid) {
 201      return false;
 202  }
 203  
 204  /**
 205   * Return read actions.
 206   *
 207   * Note: This is not used by new logging system. Event with
 208   *       crud = 'r' and edulevel = LEVEL_PARTICIPATING will
 209   *       be considered as view action.
 210   *
 211   * @return array
 212   */
 213  function book_get_view_actions() {
 214      global $CFG; // necessary for includes
 215  
 216      $return = array('view', 'view all');
 217  
 218      $plugins = core_component::get_plugin_list('booktool');
 219      foreach ($plugins as $plugin => $dir) {
 220          if (file_exists("$dir/lib.php")) {
 221              require_once("$dir/lib.php");
 222          }
 223          $function = 'booktool_'.$plugin.'_get_view_actions';
 224          if (function_exists($function)) {
 225              if ($actions = $function()) {
 226                  $return = array_merge($return, $actions);
 227              }
 228          }
 229      }
 230  
 231      return $return;
 232  }
 233  
 234  /**
 235   * Return write actions.
 236   *
 237   * Note: This is not used by new logging system. Event with
 238   *       crud = ('c' || 'u' || 'd') and edulevel = LEVEL_PARTICIPATING
 239   *       will be considered as post action.
 240   *
 241   * @return array
 242   */
 243  function book_get_post_actions() {
 244      global $CFG; // necessary for includes
 245  
 246      $return = array('update');
 247  
 248      $plugins = core_component::get_plugin_list('booktool');
 249      foreach ($plugins as $plugin => $dir) {
 250          if (file_exists("$dir/lib.php")) {
 251              require_once("$dir/lib.php");
 252          }
 253          $function = 'booktool_'.$plugin.'_get_post_actions';
 254          if (function_exists($function)) {
 255              if ($actions = $function()) {
 256                  $return = array_merge($return, $actions);
 257              }
 258          }
 259      }
 260  
 261      return $return;
 262  }
 263  
 264  /**
 265   * Supported features
 266   *
 267   * @param string $feature FEATURE_xx constant for requested feature
 268   * @return mixed True if module supports feature, false if not, null if doesn't know
 269   */
 270  function book_supports($feature) {
 271      switch($feature) {
 272          case FEATURE_MOD_ARCHETYPE:           return MOD_ARCHETYPE_RESOURCE;
 273          case FEATURE_GROUPS:                  return false;
 274          case FEATURE_GROUPINGS:               return false;
 275          case FEATURE_MOD_INTRO:               return true;
 276          case FEATURE_COMPLETION_TRACKS_VIEWS: return true;
 277          case FEATURE_GRADE_HAS_GRADE:         return false;
 278          case FEATURE_GRADE_OUTCOMES:          return false;
 279          case FEATURE_BACKUP_MOODLE2:          return true;
 280          case FEATURE_SHOW_DESCRIPTION:        return true;
 281  
 282          default: return null;
 283      }
 284  }
 285  
 286  /**
 287   * Adds module specific settings to the settings block
 288   *
 289   * @param settings_navigation $settingsnav The settings navigation object
 290   * @param navigation_node $booknode The node to add module settings to
 291   * @return void
 292   */
 293  function book_extend_settings_navigation(settings_navigation $settingsnav, navigation_node $booknode) {
 294      global $USER, $PAGE;
 295  
 296      $plugins = core_component::get_plugin_list('booktool');
 297      foreach ($plugins as $plugin => $dir) {
 298          if (file_exists("$dir/lib.php")) {
 299              require_once("$dir/lib.php");
 300          }
 301          $function = 'booktool_'.$plugin.'_extend_settings_navigation';
 302          if (function_exists($function)) {
 303              $function($settingsnav, $booknode);
 304          }
 305      }
 306  
 307      $params = $PAGE->url->params();
 308  
 309      if (!empty($params['id']) and !empty($params['chapterid']) and has_capability('mod/book:edit', $PAGE->cm->context)) {
 310          if (!empty($USER->editing)) {
 311              $string = get_string("turneditingoff");
 312              $edit = '0';
 313          } else {
 314              $string = get_string("turneditingon");
 315              $edit = '1';
 316          }
 317          $url = new moodle_url('/mod/book/view.php', array('id'=>$params['id'], 'chapterid'=>$params['chapterid'], 'edit'=>$edit, 'sesskey'=>sesskey()));
 318          $booknode->add($string, $url, navigation_node::TYPE_SETTING);
 319      }
 320  }
 321  
 322  
 323  /**
 324   * Lists all browsable file areas
 325   * @param object $course
 326   * @param object $cm
 327   * @param object $context
 328   * @return array
 329   */
 330  function book_get_file_areas($course, $cm, $context) {
 331      $areas = array();
 332      $areas['chapter'] = get_string('chapters', 'mod_book');
 333      return $areas;
 334  }
 335  
 336  /**
 337   * File browsing support for book module chapter area.
 338   * @param object $browser
 339   * @param object $areas
 340   * @param object $course
 341   * @param object $cm
 342   * @param object $context
 343   * @param string $filearea
 344   * @param int $itemid
 345   * @param string $filepath
 346   * @param string $filename
 347   * @return object file_info instance or null if not found
 348   */
 349  function book_get_file_info($browser, $areas, $course, $cm, $context, $filearea, $itemid, $filepath, $filename) {
 350      global $CFG, $DB;
 351  
 352      // note: 'intro' area is handled in file_browser automatically
 353  
 354      if (!has_capability('mod/book:read', $context)) {
 355          return null;
 356      }
 357  
 358      if ($filearea !== 'chapter') {
 359          return null;
 360      }
 361  
 362      require_once (__DIR__.'/locallib.php');
 363  
 364      if (is_null($itemid)) {
 365          return new book_file_info($browser, $course, $cm, $context, $areas, $filearea);
 366      }
 367  
 368      $fs = get_file_storage();
 369      $filepath = is_null($filepath) ? '/' : $filepath;
 370      $filename = is_null($filename) ? '.' : $filename;
 371      if (!$storedfile = $fs->get_file($context->id, 'mod_book', $filearea, $itemid, $filepath, $filename)) {
 372          return null;
 373      }
 374  
 375      // modifications may be tricky - may cause caching problems
 376      $canwrite = has_capability('mod/book:edit', $context);
 377  
 378      $chaptername = $DB->get_field('book_chapters', 'title', array('bookid'=>$cm->instance, 'id'=>$itemid));
 379      $chaptername = format_string($chaptername, true, array('context'=>$context));
 380  
 381      $urlbase = $CFG->wwwroot.'/pluginfile.php';
 382      return new file_info_stored($browser, $context, $storedfile, $urlbase, $chaptername, true, true, $canwrite, false);
 383  }
 384  
 385  /**
 386   * Serves the book attachments. Implements needed access control ;-)
 387   *
 388   * @param stdClass $course course object
 389   * @param cm_info $cm course module object
 390   * @param context $context context object
 391   * @param string $filearea file area
 392   * @param array $args extra arguments
 393   * @param bool $forcedownload whether or not force download
 394   * @param array $options additional options affecting the file serving
 395   * @return bool false if file not found, does not return if found - just send the file
 396   */
 397  function book_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options=array()) {
 398      global $CFG, $DB;
 399  
 400      if ($context->contextlevel != CONTEXT_MODULE) {
 401          return false;
 402      }
 403  
 404      require_course_login($course, true, $cm);
 405  
 406      if ($filearea !== 'chapter') {
 407          return false;
 408      }
 409  
 410      if (!has_capability('mod/book:read', $context)) {
 411          return false;
 412      }
 413  
 414      $chid = (int)array_shift($args);
 415  
 416      if (!$book = $DB->get_record('book', array('id'=>$cm->instance))) {
 417          return false;
 418      }
 419  
 420      if (!$chapter = $DB->get_record('book_chapters', array('id'=>$chid, 'bookid'=>$book->id))) {
 421          return false;
 422      }
 423  
 424      if ($chapter->hidden and !has_capability('mod/book:viewhiddenchapters', $context)) {
 425          return false;
 426      }
 427  
 428      // Download the contents of a chapter as an html file.
 429      if ($args[0] == 'index.html') {
 430          $filename = "index.html";
 431  
 432          // We need to rewrite the pluginfile URLs so the media filters can work.
 433          $content = file_rewrite_pluginfile_urls($chapter->content, 'webservice/pluginfile.php', $context->id, 'mod_book', 'chapter',
 434                                                  $chapter->id);
 435          $formatoptions = new stdClass;
 436          $formatoptions->noclean = true;
 437          $formatoptions->overflowdiv = true;
 438          $formatoptions->context = $context;
 439  
 440          $content = format_text($content, $chapter->contentformat, $formatoptions);
 441  
 442          // Remove @@PLUGINFILE@@/.
 443          $options = array('reverse' => true);
 444          $content = file_rewrite_pluginfile_urls($content, 'webservice/pluginfile.php', $context->id, 'mod_book', 'chapter',
 445                                                  $chapter->id, $options);
 446          $content = str_replace('@@PLUGINFILE@@/', '', $content);
 447  
 448          $titles = "";
 449          // Format the chapter titles.
 450          if (!$book->customtitles) {
 451              require_once (__DIR__.'/locallib.php');
 452              $chapters = book_preload_chapters($book);
 453  
 454              if (!$chapter->subchapter) {
 455                  $currtitle = book_get_chapter_title($chapter->id, $chapters, $book, $context);
 456                  // Note that we can't use the $OUTPUT->heading() in WS_SERVER mode.
 457                  $titles = "<h3>$currtitle</h3>";
 458              } else {
 459                  $currtitle = book_get_chapter_title($chapters[$chapter->id]->parent, $chapters, $book, $context);
 460                  $currsubtitle = book_get_chapter_title($chapter->id, $chapters, $book, $context);
 461                  // Note that we can't use the $OUTPUT->heading() in WS_SERVER mode.
 462                  $titles = "<h3>$currtitle</h3>";
 463                  $titles .= "<h4>$currsubtitle</h4>";
 464              }
 465          }
 466  
 467          $content = $titles . $content;
 468  
 469          send_file($content, $filename, 0, 0, true, true);
 470      } else {
 471          $fs = get_file_storage();
 472          $relativepath = implode('/', $args);
 473          $fullpath = "/$context->id/mod_book/chapter/$chid/$relativepath";
 474          if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) {
 475              return false;
 476          }
 477  
 478          // Nasty hack because we do not have file revisions in book yet.
 479          $lifetime = $CFG->filelifetime;
 480          if ($lifetime > 60 * 10) {
 481              $lifetime = 60 * 10;
 482          }
 483  
 484          // Finally send the file.
 485          send_stored_file($file, $lifetime, 0, $forcedownload, $options);
 486      }
 487  }
 488  
 489  /**
 490   * Return a list of page types
 491   *
 492   * @param string $pagetype current page type
 493   * @param stdClass $parentcontext Block's parent context
 494   * @param stdClass $currentcontext Current context of block
 495   * @return array
 496   */
 497  function book_page_type_list($pagetype, $parentcontext, $currentcontext) {
 498      $module_pagetype = array('mod-book-*'=>get_string('page-mod-book-x', 'mod_book'));
 499      return $module_pagetype;
 500  }
 501  
 502  /**
 503   * Export book resource contents
 504   *
 505   * @param  stdClass $cm     Course module object
 506   * @param  string $baseurl  Base URL for file downloads
 507   * @return array of file content
 508   */
 509  function book_export_contents($cm, $baseurl) {
 510      global $DB;
 511  
 512      $contents = array();
 513      $context = context_module::instance($cm->id);
 514  
 515      $book = $DB->get_record('book', array('id' => $cm->instance), '*', MUST_EXIST);
 516  
 517      $fs = get_file_storage();
 518  
 519      $chapters = $DB->get_records('book_chapters', array('bookid' => $book->id), 'pagenum');
 520  
 521      $structure = array();
 522      $currentchapter = 0;
 523  
 524      foreach ($chapters as $chapter) {
 525          if ($chapter->hidden) {
 526              continue;
 527          }
 528  
 529          // Generate the book structure.
 530          $thischapter = array(
 531              "title"     => format_string($chapter->title, true, array('context' => $context)),
 532              "href"      => $chapter->id . "/index.html",
 533              "level"     => 0,
 534              "subitems"  => array()
 535          );
 536  
 537          // Main chapter.
 538          if (!$chapter->subchapter) {
 539              $currentchapter = $chapter->pagenum;
 540              $structure[$currentchapter] = $thischapter;
 541          } else {
 542              // Subchapter.
 543              $thischapter['level'] = 1;
 544              $structure[$currentchapter]["subitems"][] = $thischapter;
 545          }
 546  
 547          // Export the chapter contents.
 548  
 549          // Main content (html).
 550          $filename = 'index.html';
 551          $chapterindexfile = array();
 552          $chapterindexfile['type']         = 'file';
 553          $chapterindexfile['filename']     = $filename;
 554          // Each chapter in a subdirectory.
 555          $chapterindexfile['filepath']     = "/{$chapter->id}/";
 556          $chapterindexfile['filesize']     = 0;
 557          $chapterindexfile['fileurl']      = moodle_url::make_webservice_pluginfile_url(
 558                      $context->id, 'mod_book', 'chapter', $chapter->id, '/', 'index.html')->out(false);
 559          $chapterindexfile['timecreated']  = $book->timecreated;
 560          $chapterindexfile['timemodified'] = $book->timemodified;
 561          $chapterindexfile['content']      = format_string($chapter->title, true, array('context' => $context));
 562          $chapterindexfile['sortorder']    = 0;
 563          $chapterindexfile['userid']       = null;
 564          $chapterindexfile['author']       = null;
 565          $chapterindexfile['license']      = null;
 566          $contents[] = $chapterindexfile;
 567  
 568          // Chapter files (images usually).
 569          $files = $fs->get_area_files($context->id, 'mod_book', 'chapter', $chapter->id, 'sortorder DESC, id ASC', false);
 570          foreach ($files as $fileinfo) {
 571              $file = array();
 572              $file['type']         = 'file';
 573              $file['filename']     = $fileinfo->get_filename();
 574              $file['filepath']     = "/{$chapter->id}" . $fileinfo->get_filepath();
 575              $file['filesize']     = $fileinfo->get_filesize();
 576              $file['fileurl']      = moodle_url::make_webservice_pluginfile_url(
 577                                          $context->id, 'mod_book', 'chapter', $chapter->id,
 578                                          $fileinfo->get_filepath(), $fileinfo->get_filename())->out(false);
 579              $file['timecreated']  = $fileinfo->get_timecreated();
 580              $file['timemodified'] = $fileinfo->get_timemodified();
 581              $file['sortorder']    = $fileinfo->get_sortorder();
 582              $file['userid']       = $fileinfo->get_userid();
 583              $file['author']       = $fileinfo->get_author();
 584              $file['license']      = $fileinfo->get_license();
 585              $contents[] = $file;
 586          }
 587      }
 588  
 589      // First content is the structure in encoded JSON format.
 590      $structurefile = array();
 591      $structurefile['type']         = 'content';
 592      $structurefile['filename']     = 'structure';
 593      $structurefile['filepath']     = "/";
 594      $structurefile['filesize']     = 0;
 595      $structurefile['fileurl']      = null;
 596      $structurefile['timecreated']  = $book->timecreated;
 597      $structurefile['timemodified'] = $book->timemodified;
 598      $structurefile['content']      = json_encode(array_values($structure));
 599      $structurefile['sortorder']    = 0;
 600      $structurefile['userid']       = null;
 601      $structurefile['author']       = null;
 602      $structurefile['license']      = null;
 603  
 604      // Add it as first element.
 605      array_unshift($contents, $structurefile);
 606  
 607      return $contents;
 608  }
 609  
 610  /**
 611   * Mark the activity completed (if required) and trigger the course_module_viewed event.
 612   *
 613   * @param  stdClass $book       book object
 614   * @param  stdClass $chapter    chapter object
 615   * @param  bool $islaschapter   is the las chapter of the book?
 616   * @param  stdClass $course     course object
 617   * @param  stdClass $cm         course module object
 618   * @param  stdClass $context    context object
 619   * @since Moodle 3.0
 620   */
 621  function book_view($book, $chapter, $islastchapter, $course, $cm, $context) {
 622  
 623      // First case, we are just opening the book.
 624      if (empty($chapter)) {
 625          \mod_book\event\course_module_viewed::create_from_book($book, $context)->trigger();
 626  
 627      } else {
 628          \mod_book\event\chapter_viewed::create_from_chapter($book, $context, $chapter)->trigger();
 629  
 630          if ($islastchapter) {
 631              // We cheat a bit here in assuming that viewing the last page means the user viewed the whole book.
 632              $completion = new completion_info($course);
 633              $completion->set_module_viewed($cm);
 634          }
 635      }
 636  }


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1