protected function check_table(xmldb_table $xmldb_table, array $metacolumns)
 {
     global $DB;
     $dbman = $DB->get_manager();
     $o = '';
     $missing_indexes = array();
     // Keys
     if ($xmldb_keys = $xmldb_table->getKeys()) {
         $o .= '        <ul>';
         foreach ($xmldb_keys as $xmldb_key) {
             $o .= '            <li>' . $this->str['key'] . ': ' . $xmldb_key->readableInfo() . ' ';
             // Primaries are skipped
             if ($xmldb_key->getType() == XMLDB_KEY_PRIMARY) {
                 $o .= '<font color="green">' . $this->str['ok'] . '</font></li>';
                 continue;
             }
             // If we aren't creating the keys or the key is a XMLDB_KEY_FOREIGN (not underlying index generated
             // automatically by the RDBMS) create the underlying (created by us) index (if doesn't exists)
             if (!$dbman->generator->getKeySQL($xmldb_table, $xmldb_key) || $xmldb_key->getType() == XMLDB_KEY_FOREIGN) {
                 // Create the interim index
                 $xmldb_index = new xmldb_index('anyname');
                 $xmldb_index->setFields($xmldb_key->getFields());
                 switch ($xmldb_key->getType()) {
                     case XMLDB_KEY_UNIQUE:
                     case XMLDB_KEY_FOREIGN_UNIQUE:
                         $xmldb_index->setUnique(true);
                         break;
                     case XMLDB_KEY_FOREIGN:
                         $xmldb_index->setUnique(false);
                         break;
                 }
                 // Check if the index exists in DB
                 if ($dbman->index_exists($xmldb_table, $xmldb_index)) {
                     $o .= '<font color="green">' . $this->str['ok'] . '</font>';
                 } else {
                     $o .= '<font color="red">' . $this->str['missing'] . '</font>';
                     // Add the missing index to the list
                     $obj = new stdClass();
                     $obj->table = $xmldb_table;
                     $obj->index = $xmldb_index;
                     $missing_indexes[] = $obj;
                 }
             }
             $o .= '</li>';
         }
         $o .= '        </ul>';
     }
     // Indexes
     if ($xmldb_indexes = $xmldb_table->getIndexes()) {
         $o .= '        <ul>';
         foreach ($xmldb_indexes as $xmldb_index) {
             $o .= '            <li>' . $this->str['index'] . ': ' . $xmldb_index->readableInfo() . ' ';
             // Check if the index exists in DB
             if ($dbman->index_exists($xmldb_table, $xmldb_index)) {
                 $o .= '<font color="green">' . $this->str['ok'] . '</font>';
             } else {
                 $o .= '<font color="red">' . $this->str['missing'] . '</font>';
                 // Add the missing index to the list
                 $obj = new stdClass();
                 $obj->table = $xmldb_table;
                 $obj->index = $xmldb_index;
                 $missing_indexes[] = $obj;
             }
             $o .= '</li>';
         }
         $o .= '        </ul>';
     }
     return array($o, $missing_indexes);
 }
Exemple #2
0
 /**
  * Given one correct xmldb_table, returns the SQL statements
  * to create it (inside one array).
  *
  * @param xmldb_table $xmldb_table An xmldb_table instance.
  * @return array An array of SQL statements, starting with the table creation SQL followed
  * by any of its comments, indexes and sequence creation SQL statements.
  */
 public function getCreateTableSQL($xmldb_table)
 {
     $results = array();
     //Array where all the sentences will be stored
     /// Table header
     $table = 'CREATE TABLE ' . $this->getTableName($xmldb_table) . ' (';
     if (!($xmldb_fields = $xmldb_table->getFields())) {
         return $results;
     }
     $sequencefield = null;
     /// Add the fields, separated by commas
     foreach ($xmldb_fields as $xmldb_field) {
         if ($xmldb_field->getSequence()) {
             $sequencefield = $xmldb_field->getName();
         }
         $table .= "\n    " . $this->getFieldSQL($xmldb_table, $xmldb_field);
         $table .= ',';
     }
     /// Add the keys, separated by commas
     if ($xmldb_keys = $xmldb_table->getKeys()) {
         foreach ($xmldb_keys as $xmldb_key) {
             if ($keytext = $this->getKeySQL($xmldb_table, $xmldb_key)) {
                 $table .= "\nCONSTRAINT " . $keytext . ',';
             }
             /// If the key is XMLDB_KEY_FOREIGN_UNIQUE, create it as UNIQUE too
             if ($xmldb_key->getType() == XMLDB_KEY_FOREIGN_UNIQUE) {
                 ///Duplicate the key
                 $xmldb_key->setType(XMLDB_KEY_UNIQUE);
                 if ($keytext = $this->getKeySQL($xmldb_table, $xmldb_key)) {
                     $table .= "\nCONSTRAINT " . $keytext . ',';
                 }
             }
             /// make sure sequence field is unique
             if ($sequencefield and $xmldb_key->getType() == XMLDB_KEY_PRIMARY) {
                 $field = reset($xmldb_key->getFields());
                 if ($sequencefield === $field) {
                     $sequencefield = null;
                 }
             }
         }
     }
     /// throw error if sequence field does not have unique key defined
     if ($sequencefield) {
         throw new ddl_exception('ddsequenceerror', $xmldb_table->getName());
     }
     /// Table footer, trim the latest comma
     $table = trim($table, ',');
     $table .= "\n)";
     /// Add the CREATE TABLE to results
     $results[] = $table;
     /// Add comments if specified and it exists
     if ($this->add_table_comments && $xmldb_table->getComment()) {
         $comment = $this->getCommentSQL($xmldb_table);
         /// Add the COMMENT to results
         $results = array_merge($results, $comment);
     }
     /// Add the indexes (each one, one statement)
     if ($xmldb_indexes = $xmldb_table->getIndexes()) {
         foreach ($xmldb_indexes as $xmldb_index) {
             ///tables do not exist yet, which means indexed can not exist yet
             if ($indextext = $this->getCreateIndexSQL($xmldb_table, $xmldb_index)) {
                 $results = array_merge($results, $indextext);
             }
         }
     }
     /// Also, add the indexes needed from keys, based on configuration (each one, one statement)
     if ($xmldb_keys = $xmldb_table->getKeys()) {
         foreach ($xmldb_keys as $xmldb_key) {
             /// If we aren't creating the keys OR if the key is XMLDB_KEY_FOREIGN (not underlying index generated
             /// automatically by the RDBMS) create the underlying (created by us) index (if doesn't exists)
             if (!$this->getKeySQL($xmldb_table, $xmldb_key) || $xmldb_key->getType() == XMLDB_KEY_FOREIGN) {
                 /// Create the interim index
                 $index = new xmldb_index('anyname');
                 $index->setFields($xmldb_key->getFields());
                 ///tables do not exist yet, which means indexed can not exist yet
                 $createindex = false;
                 //By default
                 switch ($xmldb_key->getType()) {
                     case XMLDB_KEY_UNIQUE:
                     case XMLDB_KEY_FOREIGN_UNIQUE:
                         $index->setUnique(true);
                         $createindex = true;
                         break;
                     case XMLDB_KEY_FOREIGN:
                         $index->setUnique(false);
                         $createindex = true;
                         break;
                 }
                 if ($createindex) {
                     if ($indextext = $this->getCreateIndexSQL($xmldb_table, $index)) {
                         /// Add the INDEX to the array
                         $results = array_merge($results, $indextext);
                     }
                 }
             }
         }
     }
     /// Add sequence extra code if needed
     if ($this->sequence_extra_code) {
         /// Iterate over fields looking for sequences
         foreach ($xmldb_fields as $xmldb_field) {
             if ($xmldb_field->getSequence()) {
                 /// returns an array of statements needed to create one sequence
                 $sequence_sentences = $this->getCreateSequenceSQL($xmldb_table, $xmldb_field);
                 /// Add the SEQUENCE to the array
                 $results = array_merge($results, $sequence_sentences);
             }
         }
     }
     return $results;
 }
 /**
  * Invoke method, every class will have its own
  * returns true/false on completion, setting both
  * errormsg and output as necessary
  */
 function invoke()
 {
     parent::invoke();
     $result = true;
     /// Set own core attributes
     $this->does_generate = ACTION_NONE;
     //$this->does_generate = ACTION_GENERATE_HTML;
     /// These are always here
     global $CFG, $XMLDB;
     /// Do the job, setting result as needed
     if (!data_submitted()) {
         ///Basic prevention
         print_error('wrongcall', 'error');
     }
     /// Get parameters
     $dirpath = required_param('dir', PARAM_PATH);
     $dirpath = $CFG->dirroot . $dirpath;
     $tableparam = strtolower(required_param('table', PARAM_PATH));
     $indexparam = strtolower(required_param('index', PARAM_PATH));
     $name = trim(strtolower(optional_param('name', $indexparam, PARAM_PATH)));
     $comment = required_param('comment', PARAM_CLEAN);
     $comment = trim($comment);
     $unique = required_param('unique', PARAM_INT);
     $fields = required_param('fields', PARAM_CLEAN);
     $fields = str_replace(' ', '', trim(strtolower($fields)));
     $editeddir =& $XMLDB->editeddirs[$dirpath];
     $structure =& $editeddir->xml_file->getStructure();
     $table =& $structure->getTable($tableparam);
     $index =& $table->getIndex($indexparam);
     $oldhash = $index->getHash();
     $errors = array();
     /// To store all the errors found
     /// Perform some checks
     /// Check empty name
     if (empty($name)) {
         $errors[] = $this->str['indexnameempty'];
     }
     /// Check incorrect name
     if ($name == 'changeme') {
         $errors[] = $this->str['incorrectindexname'];
     }
     /// Check duplicate name
     if ($indexparam != $name && $table->getIndex($name)) {
         $errors[] = $this->str['duplicateindexname'];
     }
     $fieldsarr = explode(',', $fields);
     /// Check the fields isn't empty
     if (empty($fieldsarr[0])) {
         $errors[] = $this->str['nofieldsspecified'];
     } else {
         /// Check that there aren't duplicate column names
         $uniquearr = array_unique($fieldsarr);
         if (count($fieldsarr) != count($uniquearr)) {
             $errors[] = $this->str['duplicatefieldsused'];
         }
         /// Check that all the fields in belong to the table
         foreach ($fieldsarr as $field) {
             if (!$table->getField($field)) {
                 $errors[] = $this->str['fieldsnotintable'];
                 break;
             }
         }
         /// Check that there isn't any key using exactly the same fields
         $tablekeys = $table->getKeys();
         if ($tablekeys) {
             foreach ($tablekeys as $tablekey) {
                 $keyfieldsarr = $tablekey->getFields();
                 /// Compare both arrays, looking for diferences
                 $diferences = array_merge(array_diff($fieldsarr, $keyfieldsarr), array_diff($keyfieldsarr, $fieldsarr));
                 if (empty($diferences)) {
                     $errors[] = $this->str['fieldsusedinkey'];
                     break;
                 }
             }
         }
         /// Check that there isn't any index using exactlt the same fields
         $tableindexes = $table->getIndexes();
         if ($tableindexes) {
             foreach ($tableindexes as $tableindex) {
                 /// Skip checking against itself
                 if ($indexparam == $tableindex->getName()) {
                     continue;
                 }
                 $indexfieldsarr = $tableindex->getFields();
                 /// Compare both arrays, looking for diferences
                 $diferences = array_merge(array_diff($fieldsarr, $indexfieldsarr), array_diff($indexfieldsarr, $fieldsarr));
                 if (empty($diferences)) {
                     $errors[] = $this->str['fieldsusedinindex'];
                     break;
                 }
             }
         }
     }
     if (!empty($errors)) {
         $tempindex = new xmldb_index($name);
         $tempindex->setUnique($unique);
         $tempindex->setFields($fieldsarr);
         /// Prepare the output
         $site = get_site();
         $navlinks = array();
         $navlinks[] = array('name' => $this->str['administration'], 'link' => '../index.php', 'type' => 'misc');
         $navlinks[] = array('name' => 'XMLDB', 'link' => 'index.php', 'type' => 'misc');
         $navigation = build_navigation($navlinks);
         print_header("{$site->shortname}: XMLDB", "{$site->fullname}", $navigation);
         notice('<p>' . implode(', ', $errors) . '</p>
                  <p>' . $tempindex->readableInfo() . '</p>', 'index.php?action=edit_index&amp;index=' . $index->getName() . '&amp;table=' . $table->getName() . '&amp;dir=' . urlencode(str_replace($CFG->dirroot, '', $dirpath)));
         die;
         /// re-die :-P
     }
     /// Continue if we aren't under errors
     if (empty($errors)) {
         /// If there is one name change, do it, changing the prev and next
         /// atributes of the adjacent fields
         if ($indexparam != $name) {
             $index->setName($name);
             if ($index->getPrevious()) {
                 $prev =& $table->getIndex($index->getPrevious());
                 $prev->setNext($name);
                 $prev->setChanged(true);
             }
             if ($index->getNext()) {
                 $next =& $table->getIndex($index->getNext());
                 $next->setPrevious($name);
                 $next->setChanged(true);
             }
         }
         /// Set comment
         $index->setComment($comment);
         /// Set the rest of fields
         $index->setUnique($unique);
         $index->setFields($fieldsarr);
         /// If the hash has changed from the old one, change the version
         /// and mark the structure as changed
         $index->calculateHash(true);
         if ($oldhash != $index->getHash()) {
             $index->setChanged(true);
             $table->setChanged(true);
             /// Recalculate the structure hash
             $structure->calculateHash(true);
             $structure->setVersion(userdate(time(), '%Y%m%d', 99, false));
             /// Mark as changed
             $structure->setChanged(true);
         }
         /// Launch postaction if exists (leave this here!)
         if ($this->getPostAction() && $result) {
             return $this->launch($this->getPostAction());
         }
     }
     /// Return ok if arrived here
     return $result;
 }