Search moodle.org's
Developer Documentation


  • Bug fixes for general core bugs in 2.8.x ended 9 November 2015 (12 months).
  • Bug fixes for security issues in 2.8.x ended 9 May 2016 (18 months).
  • minimum PHP 5.4.4 (always use latest PHP 5.4.x or 5.5.x on Windows - http://windows.php.net/download/), PHP 7 is NOT supported
  • /course/ -> modlib.php (source)

    Differences Between: [Versions 28 and 29] [Versions 28 and 30] [Versions 28 and 31] [Versions 28 and 32] [Versions 28 and 33] [Versions 28 and 34] [Versions 28 and 35] [Versions 28 and 36] [Versions 28 and 37]

       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   * Library of functions specific to course/modedit.php and course API functions.
      19   * The course API function calling them are course/lib.php:create_module() and update_module().
      20   * This file has been created has an alternative solution to a full refactor of course/modedit.php
      21   * in order to create the course API functions.
      22   *
      23   * @copyright 2013 Jerome Mouneyrac
      24   * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
      25   * @package core_course
      26   */
      27  
      28  defined('MOODLE_INTERNAL') || die;
      29  
      30  require_once($CFG->dirroot.'/course/lib.php');
      31  
      32  /**
      33   * Add course module.
      34   *
      35   * The function does not check user capabilities.
      36   * The function creates course module, module instance, add the module to the correct section.
      37   * It also trigger common action that need to be done after adding/updating a module.
      38   *
      39   * @param object $moduleinfo the moudle data
      40   * @param object $course the course of the module
      41   * @param object $mform this is required by an existing hack to deal with files during MODULENAME_add_instance()
      42   * @return object the updated module info
      43   */
      44  function add_moduleinfo($moduleinfo, $course, $mform = null) {
      45      global $DB, $CFG;
      46  
      47      // Attempt to include module library before we make any changes to DB.
      48      include_modulelib($moduleinfo->modulename);
      49  
      50      $moduleinfo->course = $course->id;
      51      $moduleinfo = set_moduleinfo_defaults($moduleinfo);
      52  
      53      if (!empty($course->groupmodeforce) or !isset($moduleinfo->groupmode)) {
      54          $moduleinfo->groupmode = 0; // Do not set groupmode.
      55      }
      56  
      57      // First add course_module record because we need the context.
      58      $newcm = new stdClass();
      59      $newcm->course           = $course->id;
      60      $newcm->module           = $moduleinfo->module;
      61      $newcm->instance         = 0; // Not known yet, will be updated later (this is similar to restore code).
      62      $newcm->visible          = $moduleinfo->visible;
      63      $newcm->visibleold       = $moduleinfo->visible;
      64      if (isset($moduleinfo->cmidnumber)) {
      65          $newcm->idnumber         = $moduleinfo->cmidnumber;
      66      }
      67      $newcm->groupmode        = $moduleinfo->groupmode;
      68      $newcm->groupingid       = $moduleinfo->groupingid;
      69      $completion = new completion_info($course);
      70      if ($completion->is_enabled()) {
      71          $newcm->completion                = $moduleinfo->completion;
      72          $newcm->completiongradeitemnumber = $moduleinfo->completiongradeitemnumber;
      73          $newcm->completionview            = $moduleinfo->completionview;
      74          $newcm->completionexpected        = $moduleinfo->completionexpected;
      75      }
      76      if(!empty($CFG->enableavailability)) {
      77          // This code is used both when submitting the form, which uses a long
      78          // name to avoid clashes, and by unit test code which uses the real
      79          // name in the table.
      80          $newcm->availability = null;
      81          if (property_exists($moduleinfo, 'availabilityconditionsjson')) {
      82              if ($moduleinfo->availabilityconditionsjson !== '') {
      83                  $newcm->availability = $moduleinfo->availabilityconditionsjson;
      84              }
      85          } else if (property_exists($moduleinfo, 'availability')) {
      86              $newcm->availability = $moduleinfo->availability;
      87          }
      88          // If there is any availability data, verify it.
      89          if ($newcm->availability) {
      90              $tree = new \core_availability\tree(json_decode($newcm->availability));
      91              // Save time and database space by setting null if the only data
      92              // is an empty tree.
      93              if ($tree->is_empty()) {
      94                  $newcm->availability = null;
      95              }
      96          }
      97      }
      98      if (isset($moduleinfo->showdescription)) {
      99          $newcm->showdescription = $moduleinfo->showdescription;
     100      } else {
     101          $newcm->showdescription = 0;
     102      }
     103  
     104      // From this point we make database changes, so start transaction.
     105      $transaction = $DB->start_delegated_transaction();
     106  
     107      if (!$moduleinfo->coursemodule = add_course_module($newcm)) {
     108          print_error('cannotaddcoursemodule');
     109      }
     110  
     111      if (plugin_supports('mod', $moduleinfo->modulename, FEATURE_MOD_INTRO, true) &&
     112              isset($moduleinfo->introeditor)) {
     113          $introeditor = $moduleinfo->introeditor;
     114          unset($moduleinfo->introeditor);
     115          $moduleinfo->intro       = $introeditor['text'];
     116          $moduleinfo->introformat = $introeditor['format'];
     117      }
     118  
     119      $addinstancefunction    = $moduleinfo->modulename."_add_instance";
     120      try {
     121          $returnfromfunc = $addinstancefunction($moduleinfo, $mform);
     122      } catch (moodle_exception $e) {
     123          $returnfromfunc = $e;
     124      }
     125      if (!$returnfromfunc or !is_number($returnfromfunc)) {
     126          // Undo everything we can. This is not necessary for databases which
     127          // support transactions, but improves consistency for other databases.
     128          $modcontext = context_module::instance($moduleinfo->coursemodule);
     129          context_helper::delete_instance(CONTEXT_MODULE, $moduleinfo->coursemodule);
     130          $DB->delete_records('course_modules', array('id'=>$moduleinfo->coursemodule));
     131  
     132          if ($e instanceof moodle_exception) {
     133              throw $e;
     134          } else if (!is_number($returnfromfunc)) {
     135              print_error('invalidfunction', '', course_get_url($course, $moduleinfo->section));
     136          } else {
     137              print_error('cannotaddnewmodule', '', course_get_url($course, $moduleinfo->section), $moduleinfo->modulename);
     138          }
     139      }
     140  
     141      $moduleinfo->instance = $returnfromfunc;
     142  
     143      $DB->set_field('course_modules', 'instance', $returnfromfunc, array('id'=>$moduleinfo->coursemodule));
     144  
     145      // Update embedded links and save files.
     146      $modcontext = context_module::instance($moduleinfo->coursemodule);
     147      if (!empty($introeditor)) {
     148          $moduleinfo->intro = file_save_draft_area_files($introeditor['itemid'], $modcontext->id,
     149                                                        'mod_'.$moduleinfo->modulename, 'intro', 0,
     150                                                        array('subdirs'=>true), $introeditor['text']);
     151          $DB->set_field($moduleinfo->modulename, 'intro', $moduleinfo->intro, array('id'=>$moduleinfo->instance));
     152      }
     153  
     154      // Course_modules and course_sections each contain a reference to each other.
     155      // So we have to update one of them twice.
     156      $sectionid = course_add_cm_to_section($course, $moduleinfo->coursemodule, $moduleinfo->section);
     157  
     158      // Trigger event based on the action we did.
     159      // Api create_from_cm expects modname and id property, and we don't want to modify $moduleinfo since we are returning it.
     160      $eventdata = clone $moduleinfo;
     161      $eventdata->modname = $eventdata->modulename;
     162      $eventdata->id = $eventdata->coursemodule;
     163      $event = \core\event\course_module_created::create_from_cm($eventdata, $modcontext);
     164      $event->trigger();
     165  
     166      $moduleinfo = edit_module_post_actions($moduleinfo, $course);
     167      $transaction->allow_commit();
     168  
     169      return $moduleinfo;
     170  }
     171  
     172  
     173  /**
     174   * Common create/update module module actions that need to be processed as soon as a module is created/updaded.
     175   * For example:create grade parent category, add outcomes, rebuild caches, regrade, save plagiarism settings...
     176   * Please note this api does not trigger events as of MOODLE 2.6. Please trigger events before calling this api.
     177   *
     178   * @param object $moduleinfo the module info
     179   * @param object $course the course of the module
     180   *
     181   * @return object moduleinfo update with grading management info
     182   */
     183  function edit_module_post_actions($moduleinfo, $course) {
     184      global $CFG;
     185      require_once($CFG->libdir.'/gradelib.php');
     186  
     187      $modcontext = context_module::instance($moduleinfo->coursemodule);
     188      $hasgrades = plugin_supports('mod', $moduleinfo->modulename, FEATURE_GRADE_HAS_GRADE, false);
     189      $hasoutcomes = plugin_supports('mod', $moduleinfo->modulename, FEATURE_GRADE_OUTCOMES, true);
     190  
     191      // Sync idnumber with grade_item.
     192      if ($hasgrades && $grade_item = grade_item::fetch(array('itemtype'=>'mod', 'itemmodule'=>$moduleinfo->modulename,
     193                   'iteminstance'=>$moduleinfo->instance, 'itemnumber'=>0, 'courseid'=>$course->id))) {
     194          if ($grade_item->idnumber != $moduleinfo->cmidnumber) {
     195              $grade_item->idnumber = $moduleinfo->cmidnumber;
     196              $grade_item->update();
     197          }
     198      }
     199  
     200      if ($hasgrades) {
     201          $items = grade_item::fetch_all(array('itemtype'=>'mod', 'itemmodule'=>$moduleinfo->modulename,
     202                                           'iteminstance'=>$moduleinfo->instance, 'courseid'=>$course->id));
     203      } else {
     204          $items = array();
     205      }
     206  
     207      // Create parent category if requested and move to correct parent category.
     208      if ($items and isset($moduleinfo->gradecat)) {
     209          if ($moduleinfo->gradecat == -1) {
     210              $grade_category = new grade_category();
     211              $grade_category->courseid = $course->id;
     212              $grade_category->fullname = $moduleinfo->name;
     213              $grade_category->insert();
     214              if ($grade_item) {
     215                  $parent = $grade_item->get_parent_category();
     216                  $grade_category->set_parent($parent->id);
     217              }
     218              $moduleinfo->gradecat = $grade_category->id;
     219          }
     220  
     221          foreach ($items as $itemid=>$unused) {
     222              $items[$itemid]->set_parent($moduleinfo->gradecat);
     223              if ($itemid == $grade_item->id) {
     224                  // Use updated grade_item.
     225                  $grade_item = $items[$itemid];
     226              }
     227          }
     228      }
     229  
     230      require_once($CFG->libdir.'/grade/grade_outcome.php');
     231      // Add outcomes if requested.
     232      if ($hasoutcomes && $outcomes = grade_outcome::fetch_all_available($course->id)) {
     233          $grade_items = array();
     234  
     235          // Outcome grade_item.itemnumber start at 1000, there is nothing above outcomes.
     236          $max_itemnumber = 999;
     237          if ($items) {
     238              foreach($items as $item) {
     239                  if ($item->itemnumber > $max_itemnumber) {
     240                      $max_itemnumber = $item->itemnumber;
     241                  }
     242              }
     243          }
     244  
     245          foreach($outcomes as $outcome) {
     246              $elname = 'outcome_'.$outcome->id;
     247  
     248              if (property_exists($moduleinfo, $elname) and $moduleinfo->$elname) {
     249                  // So we have a request for new outcome grade item?
     250                  if ($items) {
     251                      $outcomeexists = false;
     252                      foreach($items as $item) {
     253                          if ($item->outcomeid == $outcome->id) {
     254                              $outcomeexists = true;
     255                              break;
     256                          }
     257                      }
     258                      if ($outcomeexists) {
     259                          continue;
     260                      }
     261                  }
     262  
     263                  $max_itemnumber++;
     264  
     265                  $outcome_item = new grade_item();
     266                  $outcome_item->courseid     = $course->id;
     267                  $outcome_item->itemtype     = 'mod';
     268                  $outcome_item->itemmodule   = $moduleinfo->modulename;
     269                  $outcome_item->iteminstance = $moduleinfo->instance;
     270                  $outcome_item->itemnumber   = $max_itemnumber;
     271                  $outcome_item->itemname     = $outcome->fullname;
     272                  $outcome_item->outcomeid    = $outcome->id;
     273                  $outcome_item->gradetype    = GRADE_TYPE_SCALE;
     274                  $outcome_item->scaleid      = $outcome->scaleid;
     275                  $outcome_item->insert();
     276  
     277                  // Move the new outcome into correct category and fix sortorder if needed.
     278                  if ($grade_item) {
     279                      $outcome_item->set_parent($grade_item->categoryid);
     280                      $outcome_item->move_after_sortorder($grade_item->sortorder);
     281  
     282                  } else if (isset($moduleinfo->gradecat)) {
     283                      $outcome_item->set_parent($moduleinfo->gradecat);
     284                  }
     285              }
     286          }
     287      }
     288  
     289      if (plugin_supports('mod', $moduleinfo->modulename, FEATURE_ADVANCED_GRADING, false)
     290              and has_capability('moodle/grade:managegradingforms', $modcontext)) {
     291          require_once($CFG->dirroot.'/grade/grading/lib.php');
     292          $gradingman = get_grading_manager($modcontext, 'mod_'.$moduleinfo->modulename);
     293          $showgradingmanagement = false;
     294          foreach ($gradingman->get_available_areas() as $areaname => $aretitle) {
     295              $formfield = 'advancedgradingmethod_'.$areaname;
     296              if (isset($moduleinfo->{$formfield})) {
     297                  $gradingman->set_area($areaname);
     298                  $methodchanged = $gradingman->set_active_method($moduleinfo->{$formfield});
     299                  if (empty($moduleinfo->{$formfield})) {
     300                      // Going back to the simple direct grading is not a reason to open the management screen.
     301                      $methodchanged = false;
     302                  }
     303                  $showgradingmanagement = $showgradingmanagement || $methodchanged;
     304              }
     305          }
     306          // Update grading management information.
     307          $moduleinfo->gradingman = $gradingman;
     308          $moduleinfo->showgradingmanagement = $showgradingmanagement;
     309      }
     310  
     311      rebuild_course_cache($course->id, true);
     312      if ($hasgrades) {
     313          grade_regrade_final_grades($course->id);
     314      }
     315      require_once($CFG->libdir.'/plagiarismlib.php');
     316      plagiarism_save_form_elements($moduleinfo);
     317  
     318      return $moduleinfo;
     319  }
     320  
     321  
     322  /**
     323   * Set module info default values for the unset module attributs.
     324   *
     325   * @param object $moduleinfo the current known data of the module
     326   * @return object the completed module info
     327   */
     328  function set_moduleinfo_defaults($moduleinfo) {
     329  
     330      if (empty($moduleinfo->coursemodule)) {
     331          // Add.
     332          $cm = null;
     333          $moduleinfo->instance     = '';
     334          $moduleinfo->coursemodule = '';
     335      } else {
     336          // Update.
     337          $cm = get_coursemodule_from_id('', $moduleinfo->coursemodule, 0, false, MUST_EXIST);
     338          $moduleinfo->instance     = $cm->instance;
     339          $moduleinfo->coursemodule = $cm->id;
     340      }
     341      // For safety.
     342      $moduleinfo->modulename = clean_param($moduleinfo->modulename, PARAM_PLUGIN);
     343  
     344      if (!isset($moduleinfo->groupingid)) {
     345          $moduleinfo->groupingid = 0;
     346      }
     347  
     348      if (!isset($moduleinfo->name)) { // Label.
     349          $moduleinfo->name = $moduleinfo->modulename;
     350      }
     351  
     352      if (!isset($moduleinfo->completion)) {
     353          $moduleinfo->completion = COMPLETION_DISABLED;
     354      }
     355      if (!isset($moduleinfo->completionview)) {
     356          $moduleinfo->completionview = COMPLETION_VIEW_NOT_REQUIRED;
     357      }
     358      if (!isset($moduleinfo->completionexpected)) {
     359          $moduleinfo->completionexpected = 0;
     360      }
     361  
     362      // Convert the 'use grade' checkbox into a grade-item number: 0 if checked, null if not.
     363      if (isset($moduleinfo->completionusegrade) && $moduleinfo->completionusegrade) {
     364          $moduleinfo->completiongradeitemnumber = 0;
     365      } else {
     366          $moduleinfo->completiongradeitemnumber = null;
     367      }
     368  
     369      if (!isset($moduleinfo->conditiongradegroup)) {
     370          $moduleinfo->conditiongradegroup = array();
     371      }
     372      if (!isset($moduleinfo->conditionfieldgroup)) {
     373          $moduleinfo->conditionfieldgroup = array();
     374      }
     375  
     376      return $moduleinfo;
     377  }
     378  
     379  /**
     380   * Check that the user can add a module. Also returns some information like the module, context and course section info.
     381   * The fucntion create the course section if it doesn't exist.
     382   *
     383   * @param object $course the course of the module
     384   * @param object $modulename the module name
     385   * @param object $section the section of the module
     386   * @return array list containing module, context, course section.
     387   * @throws moodle_exception if user is not allowed to perform the action or module is not allowed in this course
     388   */
     389  function can_add_moduleinfo($course, $modulename, $section) {
     390      global $DB;
     391  
     392      $module = $DB->get_record('modules', array('name'=>$modulename), '*', MUST_EXIST);
     393  
     394      $context = context_course::instance($course->id);
     395      require_capability('moodle/course:manageactivities', $context);
     396  
     397      course_create_sections_if_missing($course, $section);
     398      $cw = get_fast_modinfo($course)->get_section_info($section);
     399  
     400      if (!course_allowed_module($course, $module->name)) {
     401          print_error('moduledisable');
     402      }
     403  
     404      return array($module, $context, $cw);
     405  }
     406  
     407  /**
     408   * Check if user is allowed to update module info and returns related item/data to the module.
     409   *
     410   * @param object $cm course module
     411   * @return array - list of course module, context, module, moduleinfo, and course section.
     412   * @throws moodle_exception if user is not allowed to perform the action
     413   */
     414  function can_update_moduleinfo($cm) {
     415      global $DB;
     416  
     417      // Check the $USER has the right capability.
     418      $context = context_module::instance($cm->id);
     419      require_capability('moodle/course:manageactivities', $context);
     420  
     421      // Check module exists.
     422      $module = $DB->get_record('modules', array('id'=>$cm->module), '*', MUST_EXIST);
     423  
     424      // Check the moduleinfo exists.
     425      $data = $DB->get_record($module->name, array('id'=>$cm->instance), '*', MUST_EXIST);
     426  
     427      // Check the course section exists.
     428      $cw = $DB->get_record('course_sections', array('id'=>$cm->section), '*', MUST_EXIST);
     429  
     430      return array($cm, $context, $module, $data, $cw);
     431  }
     432  
     433  
     434  /**
     435   * Update the module info.
     436   * This function doesn't check the user capabilities. It updates the course module and the module instance.
     437   * Then execute common action to create/update module process (trigger event, rebuild cache, save plagiarism settings...).
     438   *
     439   * @param object $cm course module
     440   * @param object $moduleinfo module info
     441   * @param object $course course of the module
     442   * @param object $mform - the mform is required by some specific module in the function MODULE_update_instance(). This is due to a hack in this function.
     443   * @return array list of course module and module info.
     444   */
     445  function update_moduleinfo($cm, $moduleinfo, $course, $mform = null) {
     446      global $DB, $CFG;
     447  
     448      // Attempt to include module library before we make any changes to DB.
     449      include_modulelib($moduleinfo->modulename);
     450  
     451      $moduleinfo->course = $course->id;
     452      $moduleinfo = set_moduleinfo_defaults($moduleinfo);
     453  
     454      if (!empty($course->groupmodeforce) or !isset($moduleinfo->groupmode)) {
     455          $moduleinfo->groupmode = $cm->groupmode; // Keep original.
     456      }
     457  
     458      // Update course module first.
     459      $cm->groupmode = $moduleinfo->groupmode;
     460      if (isset($moduleinfo->groupingid)) {
     461          $cm->groupingid = $moduleinfo->groupingid;
     462      }
     463  
     464      $completion = new completion_info($course);
     465      if ($completion->is_enabled()) {
     466          // Completion settings that would affect users who have already completed
     467          // the activity may be locked; if so, these should not be updated.
     468          if (!empty($moduleinfo->completionunlocked)) {
     469              $cm->completion = $moduleinfo->completion;
     470              $cm->completiongradeitemnumber = $moduleinfo->completiongradeitemnumber;
     471              $cm->completionview = $moduleinfo->completionview;
     472          }
     473          // The expected date does not affect users who have completed the activity,
     474          // so it is safe to update it regardless of the lock status.
     475          $cm->completionexpected = $moduleinfo->completionexpected;
     476      }
     477      if (!empty($CFG->enableavailability)) {
     478          // This code is used both when submitting the form, which uses a long
     479          // name to avoid clashes, and by unit test code which uses the real
     480          // name in the table.
     481          if (property_exists($moduleinfo, 'availabilityconditionsjson')) {
     482              if ($moduleinfo->availabilityconditionsjson !== '') {
     483                  $cm->availability = $moduleinfo->availabilityconditionsjson;
     484              } else {
     485                  $cm->availability = null;
     486              }
     487          } else if (property_exists($moduleinfo, 'availability')) {
     488              $cm->availability = $moduleinfo->availability;
     489          }
     490          // If there is any availability data, verify it.
     491          if ($cm->availability) {
     492              $tree = new \core_availability\tree(json_decode($cm->availability));
     493              // Save time and database space by setting null if the only data
     494              // is an empty tree.
     495              if ($tree->is_empty()) {
     496                  $cm->availability = null;
     497              }
     498          }
     499      }
     500      if (isset($moduleinfo->showdescription)) {
     501          $cm->showdescription = $moduleinfo->showdescription;
     502      } else {
     503          $cm->showdescription = 0;
     504      }
     505  
     506      $DB->update_record('course_modules', $cm);
     507  
     508      $modcontext = context_module::instance($moduleinfo->coursemodule);
     509  
     510      // Update embedded links and save files.
     511      if (plugin_supports('mod', $moduleinfo->modulename, FEATURE_MOD_INTRO, true)) {
     512          $moduleinfo->intro = file_save_draft_area_files($moduleinfo->introeditor['itemid'], $modcontext->id,
     513                                                        'mod_'.$moduleinfo->modulename, 'intro', 0,
     514                                                        array('subdirs'=>true), $moduleinfo->introeditor['text']);
     515          $moduleinfo->introformat = $moduleinfo->introeditor['format'];
     516          unset($moduleinfo->introeditor);
     517      }
     518      $updateinstancefunction = $moduleinfo->modulename."_update_instance";
     519      if (!$updateinstancefunction($moduleinfo, $mform)) {
     520          print_error('cannotupdatemod', '', course_get_url($course, $cw->section), $moduleinfo->modulename);
     521      }
     522  
     523      // Make sure visibility is set correctly (in particular in calendar).
     524      if (has_capability('moodle/course:activityvisibility', $modcontext)) {
     525          set_coursemodule_visible($moduleinfo->coursemodule, $moduleinfo->visible);
     526      }
     527  
     528      if (isset($moduleinfo->cmidnumber)) { // Label.
     529          // Set cm idnumber - uniqueness is already verified by form validation.
     530          set_coursemodule_idnumber($moduleinfo->coursemodule, $moduleinfo->cmidnumber);
     531      }
     532  
     533      // Now that module is fully updated, also update completion data if required.
     534      // (this will wipe all user completion data and recalculate it)
     535      if ($completion->is_enabled() && !empty($moduleinfo->completionunlocked)) {
     536          $completion->reset_all_state($cm);
     537      }
     538      $cm->name = $moduleinfo->name;
     539      \core\event\course_module_updated::create_from_cm($cm, $modcontext)->trigger();
     540  
     541      $moduleinfo = edit_module_post_actions($moduleinfo, $course);
     542  
     543      return array($cm, $moduleinfo);
     544  }
     545  
     546  /**
     547   * Include once the module lib file.
     548   *
     549   * @param string $modulename module name of the lib to include
     550   * @throws moodle_exception if lib.php file for the module does not exist
     551   */
     552  function include_modulelib($modulename) {
     553      global $CFG;
     554      $modlib = "$CFG->dirroot/mod/$modulename/lib.php";
     555      if (file_exists($modlib)) {
     556          include_once($modlib);
     557      } else {
     558          throw new moodle_exception('modulemissingcode', '', '', $modlib);
     559      }
     560  }
     561  
    

    Search This Site: