[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/dtl/ -> database_importer.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   * General database importer class
  19   *
  20   * @package    core_dtl
  21   * @copyright  2008 Andrei Bautu
  22   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23   */
  24  
  25  defined('MOODLE_INTERNAL') || die();
  26  
  27  /**
  28   * Base class for database import operations. This class implements
  29   * basic callbacks for import operations and defines the @see import_database
  30   * method as a common method for all importers. In general, subclasses will
  31   * override import_database and call other methods in appropriate moments.
  32   * Between a single pair of calls to @see begin_database_import and
  33   * @see finish_database_import, multiple non-overlapping pairs of calls may
  34   * be made to @see begin_table_import and @see finish_database_import for
  35   * different tables.
  36   * Between one pair of calls to @see begin_table_import and
  37   * @see finish_database_import multiple calls may be made to
  38   * @see import_table_data for the same table.
  39   * This class can be used directly, if the standard control flow (defined above)
  40   * is respected.
  41   */
  42  class database_importer {
  43      /** @var moodle_database Connection to the target database (a @see moodle_database object). */
  44      protected $mdb;
  45      /** @var database_manager Database manager of the target database (a @see database_manager object). */
  46      protected $manager;
  47      /** @var xmldb_structure Target database schema in XMLDB format (a @see xmldb_structure object). */
  48      protected $schema;
  49      /**
  50       * Boolean flag - whether or not to check that XML database schema matches
  51       * the RDBMS database schema before importing (used by
  52       * @see begin_database_import).
  53       * @var bool
  54       */
  55      protected $check_schema;
  56      /** @var string How to use transactions. */
  57      protected $transactionmode = 'allinone';
  58      /** @var moodle_transaction Transaction object */
  59      protected $transaction;
  60  
  61      /**
  62       * Object constructor.
  63       *
  64       * @param moodle_database $mdb Connection to the target database (a
  65       * @see moodle_database object). Use null to use the current $DB connection.
  66       * @param boolean $check_schema - whether or not to check that XML database
  67       * schema matches the RDBMS database schema before importing (inside
  68       * @see begin_database_import).
  69       */
  70      public function __construct(moodle_database $mdb, $check_schema=true) {
  71          $this->mdb          = $mdb;
  72          $this->manager      = $mdb->get_manager();
  73          $this->schema       = $this->manager->get_install_xml_schema();
  74          $this->check_schema = $check_schema;
  75      }
  76  
  77      /**
  78       * How to use transactions during the import.
  79       * @param string $mode 'pertable', 'allinone' or 'none'.
  80       */
  81      public function set_transaction_mode($mode) {
  82          if (!in_array($mode, array('pertable', 'allinone', 'none'))) {
  83              throw new coding_exception('Unknown transaction mode', $mode);
  84          }
  85          $this->transactionmode = $mode;
  86      }
  87  
  88      /**
  89       * Callback function. Should be called only once database per import
  90       * operation, before any database changes are made. It will check the database
  91       * schema if @see check_schema is true
  92       *
  93       * @throws dbtransfer_exception if any checking (e.g. database schema, Moodle
  94       * version) fails
  95       *
  96       * @param float $version the version of the system which generated the data
  97       * @param string $timestamp the timestamp of the data (in ISO 8601) format.
  98       * @return void
  99       */
 100      public function begin_database_import($version, $timestamp) {
 101          global $CFG;
 102  
 103          if (!$this->mdb->get_tables()) {
 104              // No tables present yet, time to create all tables.
 105              $this->manager->install_from_xmldb_structure($this->schema);
 106          }
 107  
 108          if (round($version, 2) !== round($CFG->version, 2)) { // version might be in decimal format too
 109              $a = (object)array('schemaver'=>$version, 'currentver'=>$CFG->version);
 110              throw new dbtransfer_exception('importversionmismatchexception', $a);
 111          }
 112  
 113          $options = array('changedcolumns' => false); // Column types may be fixed by transfer.
 114          if ($this->check_schema and $errors = $this->manager->check_database_schema($this->schema, $options)) {
 115              $details = '';
 116              foreach ($errors as $table=>$items) {
 117                  $details .= '<div>'.get_string('table').' '.$table.':';
 118                  $details .= '<ul>';
 119                  foreach ($items as $item) {
 120                      $details .= '<li>'.$item.'</li>';
 121                  }
 122                  $details .= '</ul></div>';
 123              }
 124              throw new dbtransfer_exception('importschemaexception', $details);
 125          }
 126          if ($this->transactionmode == 'allinone') {
 127              $this->transaction = $this->mdb->start_delegated_transaction();
 128          }
 129      }
 130  
 131      /**
 132       * Callback function. Should be called only once per table import operation,
 133       * before any table changes are made. It will delete all table data.
 134       *
 135       * @throws dbtransfer_exception an unknown table import is attempted
 136       * @throws ddl_table_missing_exception if the table is missing
 137       *
 138       * @param string $tablename - the name of the table that will be imported
 139       * @param string $schemaHash - the hash of the xmldb_table schema of the table
 140       * @return void
 141       */
 142      public function begin_table_import($tablename, $schemaHash) {
 143          if ($this->transactionmode == 'pertable') {
 144              $this->transaction = $this->mdb->start_delegated_transaction();
 145          }
 146          if (!$table = $this->schema->getTable($tablename)) {
 147              throw new dbtransfer_exception('unknowntableexception', $tablename);
 148          }
 149          if ($schemaHash != $table->getHash()) {
 150              throw new dbtransfer_exception('differenttableexception', $tablename);
 151          }
 152          // this should not happen, unless someone drops tables after import started
 153          if (!$this->manager->table_exists($table)) {
 154              throw new ddl_table_missing_exception($tablename);
 155          }
 156          $this->mdb->delete_records($tablename);
 157      }
 158  
 159      /**
 160       * Callback function. Should be called only once per table import operation,
 161       * after all table changes are made. It will reset table sequences if any.
 162       * @param string $tablename
 163       * @return void
 164       */
 165      public function finish_table_import($tablename) {
 166          $table  = $this->schema->getTable($tablename);
 167          $fields = $table->getFields();
 168          foreach ($fields as $field) {
 169              if ($field->getSequence()) {
 170                  $this->manager->reset_sequence($tablename);
 171                  return;
 172              }
 173          }
 174          if ($this->transactionmode == 'pertable') {
 175              $this->transaction->allow_commit();
 176          }
 177      }
 178  
 179      /**
 180       * Callback function. Should be called only once database per import
 181       * operation, after all database changes are made. It will commit changes.
 182       * @return void
 183       */
 184      public function finish_database_import() {
 185          if ($this->transactionmode == 'allinone') {
 186              $this->transaction->allow_commit();
 187          }
 188      }
 189  
 190      /**
 191       * Callback function. Should be called only once per record import operation, only
 192       * between @see begin_table_import and @see finish_table_import calls.
 193       * It will insert table data.
 194       *
 195       * @throws dml_exception if data insert operation failed
 196       *
 197       * @param string $tablename - the name of the table in which data will be
 198       * imported
 199       * @param object $data - data object (fields and values will be inserted
 200       * into table)
 201       * @return void
 202       */
 203      public function import_table_data($tablename, $data) {
 204          $this->mdb->import_record($tablename, $data);
 205      }
 206  
 207      /**
 208       * Common import method
 209       * @return void
 210       */
 211      public function import_database() {
 212          // implement in subclasses
 213      }
 214  }


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