Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

Differences Between: [Versions 401 and 402] [Versions 401 and 403]

   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   * @package   moodlecore
  18   * @subpackage backup-imscc
  19   * @copyright 2009 Mauro Rondinelli (mauro.rondinelli [AT] uvcms.com)
  20   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  21   */
  22  
  23  defined('MOODLE_INTERNAL') or die('Direct access to this script is forbidden.');
  24  
  25  require_once($CFG->dirroot . '/backup/cc/entities.class.php');
  26  require_once($CFG->dirroot . '/backup/cc/entity.label.class.php');
  27  require_once($CFG->dirroot . '/backup/cc/entity.resource.class.php');
  28  require_once($CFG->dirroot . '/backup/cc/entity.forum.class.php');
  29  require_once($CFG->dirroot . '/backup/cc/entity.quiz.class.php');
  30  
  31  class cc2moodle {
  32  
  33      const CC_TYPE_FORUM              = 'imsdt_xmlv1p0';
  34      const CC_TYPE_QUIZ               = 'imsqti_xmlv1p2/imscc_xmlv1p0/assessment';
  35      const CC_TYPE_QUESTION_BANK      = 'imsqti_xmlv1p2/imscc_xmlv1p0/question-bank';
  36      const CC_TYPE_WEBLINK            = 'imswl_xmlv1p0';
  37      const CC_TYPE_WEBCONTENT         = 'webcontent';
  38      const CC_TYPE_ASSOCIATED_CONTENT = 'associatedcontent/imscc_xmlv1p0/learning-application-resource';
  39      const CC_TYPE_EMPTY              = '';
  40  
  41      public static $restypes = array('associatedcontent/imscc_xmlv1p0/learning-application-resource', 'webcontent');
  42      public static $forumns  = array('dt' => 'http://www.imsglobal.org/xsd/imsdt_v1p0');
  43      public static $quizns   = array('xmlns' => 'http://www.imsglobal.org/xsd/ims_qtiasiv1p2');
  44      public static $resourcens = array('wl' => 'http://www.imsglobal.org/xsd/imswl_v1p0');
  45      /**
  46       *
  47       * @return array
  48       */
  49      public static function getquizns() {
  50          return static::$quizns;
  51      }
  52  
  53      /**
  54       *
  55       * @return array
  56       */
  57      public static function getforumns() {
  58          return static::$forumns;
  59      }
  60  
  61      /**
  62       *
  63       * @return array
  64       */
  65      public static function getresourcens() {
  66          return static::$resourcens;
  67      }
  68  
  69      public static function get_manifest($folder) {
  70          if (!is_dir($folder)) {
  71              return false;
  72          }
  73  
  74          // Before iterate over directories, try to find one manifest at top level
  75          if (file_exists($folder . '/imsmanifest.xml')) {
  76              return $folder . '/imsmanifest.xml';
  77          }
  78  
  79          $result = false;
  80          try {
  81              $dirIter = new RecursiveDirectoryIterator($folder, RecursiveDirectoryIterator::KEY_AS_PATHNAME);
  82              $recIter = new RecursiveIteratorIterator($dirIter, RecursiveIteratorIterator::CHILD_FIRST);
  83              foreach ($recIter as $info) {
  84                  if ($info->isFile() && ($info->getFilename() == 'imsmanifest.xml')) {
  85                      $result = $info->getPathname();
  86                      break;
  87                  }
  88              }
  89          } catch (Exception $e) {}
  90  
  91          return $result;
  92      }
  93  
  94      public static $instances = array();
  95      public static $manifest;
  96      public static $path_to_manifest_folder;
  97  
  98      public static $namespaces = array('imscc'    => 'http://www.imsglobal.org/xsd/imscc/imscp_v1p1',
  99                                        'lomimscc' => 'http://ltsc.ieee.org/xsd/imscc/LOM',
 100                                        'lom'      => 'http://ltsc.ieee.org/xsd/LOM',
 101                                        'voc'      => 'http://ltsc.ieee.org/xsd/LOM/vocab',
 102                                        'xsi'      => 'http://www.w3.org/2001/XMLSchema-instance',
 103                                        'cc'       => 'http://www.imsglobal.org/xsd/imsccauth_v1p0');
 104  
 105      function __construct ($path_to_manifest) {
 106  
 107          static::$manifest = new DOMDocument();
 108          static::$manifest->validateOnParse = false;
 109  
 110          static::$path_to_manifest_folder = dirname($path_to_manifest);
 111  
 112          static::log_action('Proccess start');
 113          static::log_action('Load the manifest file: ' . $path_to_manifest);
 114  
 115          if (!static::$manifest->load($path_to_manifest, LIBXML_NONET)) {
 116              static::log_action('Cannot load the manifest file: ' . $path_to_manifest, true);
 117          }
 118      }
 119  
 120      public function is_auth () {
 121  
 122          $xpath = static::newx_path(static::$manifest, static::$namespaces);
 123  
 124          $count_auth = $xpath->evaluate('count(/imscc:manifest/cc:authorizations)');
 125  
 126          if ($count_auth > 0) {
 127              $response = true;
 128          } else {
 129              $response = false;
 130          }
 131  
 132          return $response;
 133      }
 134  
 135      protected function get_metadata ($section, $key) {
 136  
 137          $xpath = static::newx_path(static::$manifest, static::$namespaces);
 138  
 139          $metadata = $xpath->query('/imscc:manifest/imscc:metadata/lomimscc:lom/lomimscc:' . $section . '/lomimscc:' . $key . '/lomimscc:string');
 140          $value = !empty($metadata->item(0)->nodeValue) ? $metadata->item(0)->nodeValue : '';
 141  
 142          return $value;
 143      }
 144  
 145      public function generate_moodle_xml () {
 146  
 147          global $CFG, $OUTPUT;
 148  
 149          $cdir = static::$path_to_manifest_folder . DIRECTORY_SEPARATOR . 'course_files';
 150  
 151          if (!file_exists($cdir)) {
 152              mkdir($cdir, $CFG->directorypermissions, true);
 153          }
 154  
 155          $sheet_base = static::loadsheet(SHEET_BASE);
 156  
 157          // MOODLE_BACKUP / INFO / DETAILS / MOD
 158          $node_info_details_mod = $this->create_code_info_details_mod();
 159  
 160          // MOODLE_BACKUP / BLOCKS / BLOCK
 161          $node_course_blocks_block = $this->create_node_course_blocks_block();
 162  
 163          // MOODLE_BACKUP / COURSES / SECTIONS / SECTION
 164          $node_course_sections_section = $this->create_node_course_sections_section();
 165  
 166          // MOODLE_BACKUP / COURSES / QUESTION_CATEGORIES
 167          $node_course_question_categories = $this->create_node_question_categories();
 168  
 169          // MOODLE_BACKUP / COURSES / MODULES / MOD
 170          $node_course_modules_mod = $this->create_node_course_modules_mod();
 171  
 172          // MOODLE_BACKUP / COURSE / HEADER
 173          $node_course_header = $this->create_node_course_header();
 174  
 175          // GENERAL INFO
 176          $filename = optional_param('file', 'not_available.zip', PARAM_RAW);
 177          $filename = basename($filename);
 178  
 179          $www_root = $CFG->wwwroot;
 180  
 181          $find_tags = array('[#zip_filename#]',
 182                             '[#www_root#]',
 183                             '[#node_course_header#]',
 184                             '[#node_info_details_mod#]',
 185                             '[#node_course_blocks_block#]',
 186                             '[#node_course_sections_section#]',
 187                             '[#node_course_question_categories#]',
 188                             '[#node_course_modules#]');
 189  
 190          $replace_values = array($filename,
 191                                  $www_root,
 192                                  $node_course_header,
 193                                  $node_info_details_mod,
 194                                  $node_course_blocks_block,
 195                                  $node_course_sections_section,
 196                                  $node_course_question_categories,
 197                                  $node_course_modules_mod);
 198  
 199          $result_xml = str_replace($find_tags, $replace_values, $sheet_base);
 200  
 201          // COPY RESOURSE FILES
 202          $entities = new entities();
 203  
 204          $entities->move_all_files();
 205  
 206          if (array_key_exists("index", self::$instances)) {
 207  
 208              if (!file_put_contents(static::$path_to_manifest_folder . DIRECTORY_SEPARATOR . 'moodle.xml', $result_xml)) {
 209                  static::log_action('Cannot save the moodle manifest file: ' . static::$path_to_tmp_folder . DIRECTORY_SEPARATOR . 'moodle.xml', true);
 210              } else {
 211                  $status = true;
 212              }
 213  
 214          } else {
 215              $status = false;
 216              echo $OUTPUT->notification('The course is empty');
 217              static::log_action('The course is empty', false);
 218          }
 219  
 220          return $status;
 221  
 222      }
 223  
 224      protected function get_sections_numbers ($instances) {
 225  
 226          $count = 0;
 227  
 228          if (array_key_exists("index", $instances)) {
 229              foreach ($instances["index"] as $instance) {
 230                  if ($instance["deep"] == ROOT_DEEP) {
 231                      $count++;
 232                  }
 233              }
 234          }
 235  
 236          return $count;
 237      }
 238  
 239      protected function create_node_course_header () {
 240  
 241          $node_course_header = '';
 242          $sheet_course_header = static::loadsheet(SHEET_COURSE_HEADER);
 243  
 244          $course_title = trim($this->get_metadata('general', 'title'));
 245          $course_title = empty($course_title) ? 'Untitled Course' : $course_title;
 246          $course_description = $this->get_metadata('general', 'description');
 247          $section_count = $this->get_sections_numbers(static::$instances) - 1;
 248  
 249          if ($section_count == -1) {
 250              $section_count = 0;
 251          }
 252  
 253          if (empty($course_title)) {
 254              $this->log_action('The course title not found', true);
 255          }
 256  
 257          $course_short_name = $this->create_course_code($course_title);
 258  
 259          $find_tags = array('[#course_name#]',
 260                             '[#course_short_name#]',
 261                             '[#course_description#]',
 262                             '[#date_now#]',
 263                             '[#section_count#]');
 264  
 265          $replace_values = array(entities::safexml($course_title),
 266                                  entities::safexml($course_short_name),
 267                                  entities::safexml($course_description),
 268                                  time(),
 269                                  $section_count);
 270  
 271          $node_course_header = str_replace($find_tags, $replace_values, $sheet_course_header);
 272  
 273          return $node_course_header;
 274      }
 275  
 276      protected function create_node_question_categories () {
 277  
 278          $quiz = new cc_quiz();
 279  
 280          static::log_action('Creating node: QUESTION_CATEGORIES');
 281  
 282          $node_course_question_categories = $quiz->generate_node_question_categories();
 283  
 284          return $node_course_question_categories;
 285      }
 286  
 287      protected function create_node_course_modules_mod () {
 288  
 289          $labels = new cc_label();
 290          $resources = new cc_resource();
 291          $forums = new cc_forum();
 292          $quiz = new cc_quiz();
 293  
 294          static::log_action('Creating node: COURSE/MODULES/MOD');
 295  
 296          // LABELS
 297          $node_course_modules_mod_label = $labels->generate_node();
 298  
 299          // RESOURCES (WEB CONTENT AND WEB LINK)
 300          $node_course_modules_mod_resource = $resources->generate_node();
 301  
 302          // FORUMS
 303          $node_course_modules_mod_forum = $forums->generate_node();
 304  
 305          // QUIZ
 306          $node_course_modules_mod_quiz = $quiz->generate_node_course_modules_mod();
 307          //TODO: label
 308          $node_course_modules = $node_course_modules_mod_label . $node_course_modules_mod_resource . $node_course_modules_mod_forum . $node_course_modules_mod_quiz;
 309  
 310          return $node_course_modules;
 311      }
 312  
 313  
 314      protected function create_node_course_sections_section () {
 315  
 316          static::log_action('Creating node: COURSE/SECTIONS/SECTION');
 317  
 318          $node_course_sections_section = '';
 319          $sheet_course_sections_section = static::loadsheet(SHEET_COURSE_SECTIONS_SECTION);
 320  
 321          $topics = $this->get_nodes_by_criteria('deep', ROOT_DEEP);
 322  
 323          $i = 0;
 324  
 325          if (!empty($topics)) {
 326  
 327              foreach ($topics as $topic) {
 328  
 329                  $i++;
 330                  $node_node_course_sections_section_mods_mod = $this->create_node_course_sections_section_mods_mod($topic['index']);
 331  
 332                  if ($topic['moodle_type'] == MOODLE_TYPE_LABEL) {
 333  
 334                      $find_tags = array('[#section_id#]',
 335                                         '[#section_number#]',
 336                                         '[#section_summary#]',
 337                                         '[#node_course_sections_section_mods_mod#]');
 338  
 339                      $replace_values = array($i,
 340                                              $i - 1,
 341                                              entities::safexml($topic['title']),
 342                                              $node_node_course_sections_section_mods_mod);
 343  
 344                  } else {
 345  
 346                      $find_tags = array('[#section_id#]',
 347                                         '[#section_number#]',
 348                                         '[#section_summary#]',
 349                                         '[#node_course_sections_section_mods_mod#]');
 350  
 351                      $replace_values = array($i,
 352                                              $i - 1,
 353                                              '',
 354                                              $node_node_course_sections_section_mods_mod);
 355  
 356                  }
 357  
 358                  $node_course_sections_section .= str_replace($find_tags, $replace_values, $sheet_course_sections_section);
 359              }
 360          }
 361  
 362  
 363          return $node_course_sections_section;
 364      }
 365  
 366      protected function create_node_course_blocks_block () {
 367  
 368          global $CFG;
 369  
 370          static::log_action('Creating node: COURSE/BLOCKS/BLOCK');
 371  
 372          $sheet_course_blocks_block = static::loadsheet(SHEET_COURSE_BLOCKS_BLOCK);
 373          $node_course_blocks_block = '';
 374  
 375          $format_config = $CFG->dirroot . '/course/format/weeks/config.php';
 376  
 377          if (@is_file($format_config) && is_readable($format_config)) {
 378              require ($format_config);
 379          }
 380  
 381          if (!empty($format['defaultblocks'])) {
 382              $blocknames = $format['defaultblocks'];
 383          } else {
 384              if (isset($CFG->defaultblocks)) {
 385                  $blocknames = $CFG->defaultblocks;
 386              } else {
 387                  $blocknames = 'activity_modules,search_forums,course_list:news_items,calendar_upcoming,recent_activity';
 388              }
 389          }
 390  
 391          $blocknames = explode(':', $blocknames);
 392          $blocks_left = explode(',', $blocknames[0]);
 393          $blocks_right = explode(',', $blocknames[1]);
 394  
 395          $find_tags = array('[#block_id#]',
 396                             '[#block_name#]',
 397                             '[#block_position#]',
 398                             '[#block_weight#]');
 399  
 400          $i = 0;
 401          $weight = 0;
 402  
 403          foreach ($blocks_left as $block) {
 404              $i++;
 405              $weight++;
 406  
 407              $replace_values = array($i,
 408                                      $block,
 409                                      'l',
 410                                      $weight);
 411  
 412              $node_course_blocks_block .= str_replace($find_tags, $replace_values, $sheet_course_blocks_block);
 413          }
 414  
 415          $weight = 0;
 416  
 417          foreach ($blocks_right as $block) {
 418  
 419              $i++;
 420              $weight ++;
 421  
 422              $replace_values = array($i,
 423                                      $block,
 424                                      'r',
 425                                      $weight);
 426  
 427              $node_course_blocks_block .= str_replace($find_tags, $replace_values, $sheet_course_blocks_block);
 428          }
 429  
 430          return $node_course_blocks_block;
 431  
 432      }
 433  
 434      /**
 435      *
 436      * Is activity visible or not
 437      * @param string $identifier
 438      * @return number
 439      */
 440      protected function get_module_visible($identifier) {
 441          //Should item be hidden or not
 442          $mod_visible = 1;
 443          if (!empty($identifier)) {
 444              $xpath = static::newx_path(static::$manifest, static::$namespaces);
 445              $query  = '/imscc:manifest/imscc:resources/imscc:resource[@identifier="' . $identifier . '"]';
 446              $query .= '//lom:intendedEndUserRole/voc:vocabulary/lom:value';
 447              $intendeduserrole = $xpath->query($query);
 448              if (!empty($intendeduserrole) && ($intendeduserrole->length > 0)) {
 449                  $role = trim($intendeduserrole->item(0)->nodeValue);
 450                  if (strcasecmp('Instructor', $role) == 0) {
 451                      $mod_visible = 0;
 452                  }
 453              }
 454          }
 455          return $mod_visible;
 456      }
 457  
 458      protected function create_node_course_sections_section_mods_mod ($root_parent) {
 459  
 460          $sheet_course_sections_section_mods_mod = static::loadsheet(SHEET_COURSE_SECTIONS_SECTION_MODS_MOD);
 461          $childs = $this->get_nodes_by_criteria('root_parent', $root_parent);
 462  
 463          if ($childs) {
 464  
 465              $node_course_sections_section_mods_mod = '';
 466  
 467              foreach ($childs as $child) {
 468  
 469                  if ($child['moodle_type'] == MOODLE_TYPE_LABEL) {
 470                      if ($child['index'] == $child['root_parent']) {
 471                          $is_summary = true;
 472                      } else {
 473                          $is_summary = false;
 474                      }
 475                  } else {
 476                      $is_summary = false;
 477                  }
 478  
 479                  if (!$is_summary) {
 480  
 481                      $indent = $child['deep'] - ROOT_DEEP;
 482  
 483                      if ($indent > 0) {
 484                          $indent = $indent - 1;
 485                      }
 486  
 487                      $find_tags = array('[#mod_id#]',
 488                                         '[#mod_instance_id#]',
 489                                         '[#mod_type#]',
 490                                         '[#date_now#]',
 491                                         '[#mod_indent#]',
 492                                         '[#mod_visible#]');
 493  
 494                      $replace_values = array($child['index'],
 495                                              $child['instance'],
 496                                              $child['moodle_type'],
 497                                              time(),
 498                                              $indent,
 499                                              $this->get_module_visible($child['resource_indentifier']));
 500  
 501                      $node_course_sections_section_mods_mod .= str_replace($find_tags, $replace_values, $sheet_course_sections_section_mods_mod);
 502                  }
 503              }
 504  
 505              $response = $node_course_sections_section_mods_mod;
 506  
 507          } else {
 508              $response = '';
 509          }
 510  
 511          return $response;
 512  
 513      }
 514  
 515      public function get_nodes_by_criteria ($key, $value) {
 516  
 517          $response = array();
 518  
 519          if (array_key_exists('index', static::$instances)) {
 520              foreach (static::$instances['index'] as $item) {
 521                  if ($item[$key] == $value) {
 522                      $response[] = $item;
 523                  }
 524              }
 525          }
 526  
 527          return $response;
 528      }
 529  
 530      //Modified here
 531      protected function create_code_info_details_mod () {
 532  
 533          static::log_action('Creating node: INFO/DETAILS/MOD');
 534  
 535          $xpath = static::newx_path(static::$manifest, static::$namespaces);
 536  
 537          $items = $xpath->query('/imscc:manifest/imscc:organizations/imscc:organization/imscc:item | /imscc:manifest/imscc:resources/imscc:resource[@type="' . static::CC_TYPE_QUESTION_BANK . '"]');
 538  
 539          $this->create_instances($items);
 540  
 541          $count_quiz = $this->count_instances(MOODLE_TYPE_QUIZ);
 542          $count_forum = $this->count_instances(MOODLE_TYPE_FORUM);
 543          $count_resource = $this->count_instances(MOODLE_TYPE_RESOURCE);
 544          $count_label = $this->count_instances(MOODLE_TYPE_LABEL);
 545  
 546          $sheet_info_details_mod_instances_instance = static::loadsheet(SHEET_INFO_DETAILS_MOD_INSTANCE);
 547  
 548          if ($count_resource > 0) {
 549              $resource_instance = $this->create_mod_info_details_mod_instances_instance($sheet_info_details_mod_instances_instance, $count_resource, static::$instances['instances'][MOODLE_TYPE_RESOURCE]);
 550          }
 551          if ($count_quiz > 0) {
 552              $quiz_instance = $this->create_mod_info_details_mod_instances_instance($sheet_info_details_mod_instances_instance, $count_quiz, static::$instances['instances'][MOODLE_TYPE_QUIZ]);
 553          }
 554          if ($count_forum > 0) {
 555              $forum_instance = $this->create_mod_info_details_mod_instances_instance($sheet_info_details_mod_instances_instance, $count_forum, static::$instances['instances'][MOODLE_TYPE_FORUM]);
 556          }
 557          if ($count_label > 0) {
 558              $label_instance = $this->create_mod_info_details_mod_instances_instance($sheet_info_details_mod_instances_instance, $count_label, static::$instances['instances'][MOODLE_TYPE_LABEL]);
 559          }
 560  
 561          $resource_mod = $count_resource ? $this->create_mod_info_details_mod(MOODLE_TYPE_RESOURCE, $resource_instance) : '';
 562          $quiz_mod = $count_quiz ? $this->create_mod_info_details_mod(MOODLE_TYPE_QUIZ, $quiz_instance) : '';
 563          $forum_mod = $count_forum ? $this->create_mod_info_details_mod(MOODLE_TYPE_FORUM, $forum_instance) : '';
 564          $label_mod = $count_label ? $this->create_mod_info_details_mod(MOODLE_TYPE_LABEL, $label_instance) : '';
 565  
 566          //TODO: label
 567          return $label_mod . $resource_mod . $quiz_mod . $forum_mod;
 568  
 569      }
 570  
 571      protected function create_mod_info_details_mod ($mod_type, $node_info_details_mod_instances_instance) {
 572  
 573          $sheet_info_details_mod = static::loadsheet(SHEET_INFO_DETAILS_MOD);
 574  
 575          $find_tags = array('[#mod_type#]' ,'[#node_info_details_mod_instances_instance#]');
 576          $replace_values = array($mod_type , $node_info_details_mod_instances_instance);
 577  
 578          return str_replace($find_tags, $replace_values, $sheet_info_details_mod);
 579      }
 580  
 581      protected function create_mod_info_details_mod_instances_instance ($sheet, $instances_quantity, $instances) {
 582  
 583          $instance = '';
 584  
 585          $find_tags = array('[#mod_instance_id#]',
 586                             '[#mod_name#]',
 587                             '[#mod_user_info#]');
 588  
 589          for ($i = 1; $i <= $instances_quantity; $i++) {
 590  
 591              $user_info = ($instances[$i - 1]['common_cartriedge_type'] == static::CC_TYPE_FORUM) ? 'true' : 'false';
 592              if ($instances[$i - 1]['common_cartriedge_type'] == static::CC_TYPE_EMPTY) {
 593                  if ($instances[$i - 1]['deep'] <= ROOT_DEEP ) {
 594                      continue;
 595                  }
 596              }
 597  
 598              $replace_values = array($instances[$i - 1]['instance'],
 599                                      entities::safexml($instances[$i - 1]['title']),
 600                                      $user_info);
 601  
 602              $instance .= str_replace($find_tags, $replace_values, $sheet);
 603          }
 604  
 605          return $instance;
 606  
 607      }
 608  
 609      protected function create_instances ($items, $level = 0, &$array_index = 0, $index_root = 0) {
 610  
 611          $level++;
 612          $i = 1;
 613  
 614          if ($items) {
 615  
 616              $xpath = self::newx_path(static::$manifest, static::$namespaces);
 617  
 618              foreach ($items as $item) {
 619  
 620                  $array_index++;
 621  
 622                  if ($item->nodeName == "item")  {
 623                      $identifierref = '';
 624                      if ($item->hasAttribute('identifierref')) {
 625                        $identifierref = $item->getAttribute('identifierref');
 626                      }
 627  
 628                      $title = '';
 629                      $titles = $xpath->query('imscc:title', $item);
 630                      if ($titles->length > 0) {
 631                          $title = $titles->item(0)->nodeValue;
 632                      }
 633  
 634                      $cc_type = $this->get_item_cc_type($identifierref);
 635                      $moodle_type = $this->convert_to_moodle_type($cc_type);
 636                      //Fix the label issue - MDL-33523
 637                      if (empty($identifierref) && empty($title)) {
 638                        $moodle_type = TYPE_UNKNOWN;
 639                      }
 640                  }
 641                  elseif ($item->nodeName == "resource")  {
 642  
 643                      $identifierref = $xpath->query('@identifier', $item);
 644                      $identifierref = !empty($identifierref->item(0)->nodeValue) ? $identifierref->item(0)->nodeValue : '';
 645  
 646                      $cc_type = $this->get_item_cc_type($identifierref);
 647                      $moodle_type = $this->convert_to_moodle_type($cc_type);
 648  
 649                      $title = 'Quiz Bank ' . ($this->count_instances($moodle_type) + 1);
 650  
 651                  }
 652  
 653                  if ($level == ROOT_DEEP) {
 654                      $index_root = $array_index;
 655                  }
 656  
 657                  static::$instances['index'][$array_index]['common_cartriedge_type'] = $cc_type;
 658                  static::$instances['index'][$array_index]['moodle_type'] = $moodle_type;
 659                  static::$instances['index'][$array_index]['title'] = $title ? $title : '';
 660                  static::$instances['index'][$array_index]['root_parent'] = $index_root;
 661                  static::$instances['index'][$array_index]['index'] = $array_index;
 662                  static::$instances['index'][$array_index]['deep'] = $level;
 663                  static::$instances['index'][$array_index]['instance'] = $this->count_instances($moodle_type);
 664                  static::$instances['index'][$array_index]['resource_indentifier'] = $identifierref;
 665  
 666                  static::$instances['instances'][$moodle_type][] = array('title' => $title,
 667                                                                          'instance' => static::$instances['index'][$array_index]['instance'],
 668                                                                          'common_cartriedge_type' => $cc_type,
 669                                                                          'resource_indentifier' => $identifierref,
 670                                                                          'deep' => $level);
 671  
 672                  $more_items = $xpath->query('imscc:item', $item);
 673  
 674                  if ($more_items->length > 0) {
 675                      $this->create_instances($more_items, $level, $array_index, $index_root);
 676                  }
 677  
 678                  $i++;
 679  
 680              }
 681          }
 682      }
 683  
 684      public function count_instances ($type) {
 685  
 686          $quantity = 0;
 687  
 688          if (array_key_exists('index', static::$instances)) {
 689              if (static::$instances['index'] && $type) {
 690  
 691                  foreach (static::$instances['index'] as $instance) {
 692                      if (!empty($instance['moodle_type'])) {
 693                          $types[] = $instance['moodle_type'];
 694                      }
 695                  }
 696  
 697                  $quantity_instances = array_count_values($types);
 698                  $quantity = array_key_exists($type, $quantity_instances) ? $quantity_instances[$type] : 0;
 699              }
 700          }
 701  
 702          return $quantity;
 703      }
 704  
 705      public function convert_to_moodle_type ($cc_type) {
 706          $type = TYPE_UNKNOWN;
 707  
 708          if ($cc_type == static::CC_TYPE_FORUM) {
 709              $type = MOODLE_TYPE_FORUM;
 710          }
 711  
 712          if ($cc_type == static::CC_TYPE_QUIZ) {
 713              $type = MOODLE_TYPE_QUIZ;
 714          }
 715  
 716          if ($cc_type == static::CC_TYPE_WEBLINK) {
 717              $type = MOODLE_TYPE_RESOURCE;
 718          }
 719  
 720          if ($cc_type == static::CC_TYPE_WEBCONTENT) {
 721              $type = MOODLE_TYPE_RESOURCE;
 722          }
 723  
 724          if ($cc_type == static::CC_TYPE_ASSOCIATED_CONTENT) {
 725              $type = MOODLE_TYPE_RESOURCE;
 726          }
 727  
 728          if ($cc_type == static::CC_TYPE_QUESTION_BANK) {
 729              $type = MOODLE_TYPE_QUESTION_BANK;
 730          }
 731          //TODO: label
 732          if ($cc_type == static::CC_TYPE_EMPTY) {
 733              $type = MOODLE_TYPE_LABEL;
 734          }
 735  
 736          return $type;
 737      }
 738  
 739      public function get_item_cc_type ($identifier) {
 740  
 741          $xpath = static::newx_path(static::$manifest, static::$namespaces);
 742  
 743          $nodes = $xpath->query('/imscc:manifest/imscc:resources/imscc:resource[@identifier="' . $identifier . '"]/@type');
 744  
 745          if ($nodes && !empty($nodes->item(0)->nodeValue)) {
 746              return $nodes->item(0)->nodeValue;
 747          } else {
 748              return '';
 749          }
 750      }
 751  
 752      public static function newx_path (DOMDocument $manifest, $namespaces = '') {
 753  
 754          $xpath = new DOMXPath($manifest);
 755  
 756          if (!empty($namespaces)) {
 757              foreach ($namespaces as $prefix => $ns) {
 758                  if (!$xpath->registerNamespace($prefix, $ns)) {
 759                      static::log_action('Cannot register the namespace: ' . $prefix . ':' . $ns, true);
 760                  }
 761              }
 762          }
 763  
 764          return $xpath;
 765      }
 766  
 767      public static function loadsheet ($file) {
 768  
 769          $content = (is_readable($file) && ($content = file_get_contents($file))) ? $content : false;
 770  
 771          static::log_action('Loading sheet: ' . $file);
 772  
 773          if (!$content) {
 774              static::log_action('Cannot load the xml sheet: ' . $file, true);
 775          }
 776  
 777          static::log_action('Load OK!');
 778  
 779          return $content;
 780      }
 781  
 782      public static function log_file() {
 783          return static::$path_to_manifest_folder . DIRECTORY_SEPARATOR . 'cc2moodle.log';
 784      }
 785  
 786      public static function log_action ($text, $critical_error = false) {
 787  
 788          $full_message = strtoupper(date("j/n/Y g:i:s a")) . " - " . $text . "\r";
 789  
 790          file_put_contents(static::log_file(), $full_message, FILE_APPEND);
 791  
 792          if ($critical_error) {
 793              static::critical_error($text);
 794          }
 795      }
 796  
 797      protected static function critical_error ($text) {
 798  
 799          $path_to_log = static::log_file();
 800  
 801          echo '
 802  
 803          <p>
 804          <hr />A critical error has been found!
 805  
 806          <p>' . $text . '</p>
 807  
 808  
 809          <p>
 810          The process has been stopped. Please see the <a href="' . $path_to_log . '">log file</a> for more information.</p>
 811  
 812          <p>Log: ' . $path_to_log . '</p>
 813  
 814          <hr />
 815  
 816          </p>
 817          ';
 818  
 819          die();
 820      }
 821  
 822      protected function create_course_code ($title) {
 823          //Making sure that text of the short name does not go over the DB limit.
 824          //and leaving the space to add additional characters by the platform
 825          $code = substr(strtoupper(str_replace(' ', '', trim($title))),0,94);
 826          return $code;
 827      }
 828  }